Phillip J. Eby added the comment: ...and I thought of *one* more way to trigger the changed behavior, which looks like:
#b.py from .b import util import .a util = util.util #b/util.py 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.) ---------- _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue17636> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com