Re: Dabeaz's weird import discovery
Nick Coghlan <[email protected]> Sat, 25 Apr 2015 13:42:13 +1000
| Newsgroups | gmane.comp.python.import |
|---|---|
| Message-ID | <CADiSq7dcmFj79GQjmEh6dDYpeMFaPgbjxXnHo_CsBZE=XEy4AA@mail.gmail.com> |
On 23 April 2015 at 02:21, Ethan Furman <[email protected]> wrote: > On 04/22, Barry Warsaw wrote: > >> Poking around in Lib/importlib/_bootstrap.py, I think you can see where this >> happens. In _find_and_load_unlocked(), 'round about line 2224 (in 3.5's >> hg:95593), you see this: >> >> if parent: >> # Set the module as an attribute on its parent. >> parent_module = sys.modules[parent] >> setattr(parent_module, name.rpartition('.')[2], module) >> >> It's clearly intentional, and fundamental to importlib so I don't think it's >> dependent on finder or loader. No matter how it happens, if a submodule is >> imported, its parent namespace gets a name binding to the submodule. > > I see that it's intentional, but why is it fundamental? The behaviour serves to preserve the equivalence of the following two snippets of code in terms of their impact on the "foo" namespace: from foo.bar import baz and: import foo.bar baz = foo.bar.baz The only difference between the two is that the latter also binds "foo" locally, while the from-import doesn't. The explicit relative import case is just slightly more surprising as the implied "foo" that is having a submodule added is the package namespace that's currently executing: from .bar import baz When we break the invariant that "foo.bar" existing in sys.modules implies there's a "bar" attribute on the parent "foo" module, all sorts of code tends to get upset (hence the weird errors folks can get in the face of circular imports, and why we finally relented and made from-import fall back to checking in sys.modules if it encounters a missing attribute) Cheers, Nick. -- Nick Coghlan | [email protected] | Brisbane, Australia