http://bugs.python.org/issue17636 On Thu, Apr 4, 2013 at 8:03 PM, Brett Cannon <brett@python.org> wrote:
On Apr 4, 2013 6:47 PM, "Guido van Rossum" <guido@python.org> wrote:
+1 on Brett and PJE just doing this.
I'll file a bug when I get home.
-brett
On Thu, Apr 4, 2013 at 3:38 PM, Brett Cannon <brett@python.org> wrote:
On Thu, Apr 4, 2013 at 5:00 PM, PJ Eby <pje@telecommunity.com> wrote:
On Thu, Apr 4, 2013 at 4:42 PM, Guido van Rossum <guido@python.org>
I do think it would be fine if "from a import b" returned the attribute 'b' of module 'a' if it exists, and otherwise look for module 'a.b' in sys.modules.
Technically, it already does that -- but inside of __import__, not in the IMPORT_FROM opcode.
But then *after* doing that check-and-fallback, __import__ doesn't assign a.b, because it assumes the recursive import it called has already done this...
It's an unfortunate side-effect of having loaders set sys.modules for new modules not also set them as an attribute on their parent package immediately as well (or you could argue it's a side-effect of not
wrote: passing in
a module instead of a name to load_module() but that's another discussion).
which means that when __import__ returns, the IMPORT_FROM opcode tries and fails to do the getattr.
This could be fixed in one of two ways. Either:
1. Change importlib._bootstrap._handle_fromlist() to set a.b if it successfully imports 'a.b' (inside its duplicate handling for what IMPORT_FROM does), or
It's three lines, one of which is 'else:'. Just did it.
2. Change the IMPORT_FROM opcode to handle the fallback itself
While the latter involves a bit of C coding, it has fewer potential side-effects on the import system as a whole, and simply ensures that if "import" would succeed, then so would "from...import" targeting the same module.
(There might be other fixes I haven't thought of, but really, changing IMPORT_FROM to fallback to a sys.modules check is probably by far the least-invasive way to handle it.)
This is my preference as well. The change would be small: I think all you need to do is if the getattr() fails then fall back to sys.modules. Although if it were me and I was casting backwards-compatibility to the wind I would rip out the whole fromlist part of __import__() and let the bytecode worry about the fromlist, basically making the import opcode call importlib.import_module().
-- --Guido van Rossum (python.org/~guido)