[Python-Dev] relative import circular problem (original) (raw)

Guido van Rossum guido at python.org
Fri Apr 5 00:47:25 CEST 2013


+1 on Brett and PJE just doing this.

On Thu, Apr 4, 2013 at 3:38 PM, Brett Cannon <brett at python.org> wrote:

On Thu, Apr 4, 2013 at 5:00 PM, PJ Eby <pje at telecommunity.com> wrote: On Thu, Apr 4, 2013 at 4:42 PM, Guido van Rossum <guido at python.org> wrote: > 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 IMPORTFROM 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 passing in a module instead of a name to loadmodule() but that's another discussion).

which means that when import returns, the IMPORTFROM opcode tries and fails to do the getattr. This could be fixed in one of two ways. Either: 1. Change importlib.bootstrap.handlefromlist() to set a.b if it successfully imports 'a.b' (inside its duplicate handling for what IMPORTFROM does), or It's three lines, one of which is 'else:'. Just did it. 2. Change the IMPORTFROM 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 IMPORTFROM 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.importmodule().

-- --Guido van Rossum (python.org/~guido)



More information about the Python-Dev mailing list