Author pje
Recipients barry, brett.cannon, eric.snow, kristjan.jonsson, methane, pconnell, pje
Date 2013-04-05.17:49:24
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <>
In-reply-to <>
...and I thought of *one* more way to trigger the changed behavior,
which looks like:
from .b import util
import .a
util = util.util

def util(): pass

(with the other files the same as before).

I'm including it only for completeness' sake, because my original
enumeration of cases ignored the possibility that 'a' could be doing
the import *after* b.util is loaded and bound, but *before* it's
rebound.  However, it doesn't produce any new or problematic effects:
it's essentially the same as if 'a' were imported from 'b.util'.  Once
again, regardless of the order in which imports happen, 'a' ends up
with 'b.util' the moment the circularity is introduced, and it stays
that way.

It's also hard to argue that a case written this way isn't getting
exactly what it *says* it wants.  In fact, it looks like code that was
deliberately written to *force* a to end up with the original b.util
instead of the replaced one.  ;-)

Final (hopefully) conclusion: this change replaces the FAQ of "Don't
use 'from-import' for circular imports" with the hopefully-less-FA'd Q
of "when from-import is part of an import cycle, it works *exactly*
like regular import, so you're going to get a submodule rather than an
attribute.  If you need the attribute instead, move the import so that
it happens after the attribute is set up."  (Which is exactly the same
advice that would apply in a cycle with any other unitialized
attribute, whether you were using from-import or not.)
Date User Action Args
2013-04-05 17:49:24pjesetrecipients: + pje, barry, brett.cannon, kristjan.jonsson, methane, eric.snow, pconnell
2013-04-05 17:49:24pjelinkissue17636 messages
2013-04-05 17:49:24pjecreate