[Import-SIG] Dabeaz's weird import discovery
Guido van Rossum
guido at python.org
Wed Apr 22 19:15:57 CEST 2015
On Wed, Apr 22, 2015 at 8:59 AM, Barry Warsaw <barry at python.org> wrote:
> [...]
> As it turns out, it's not the from-import-* that does the name binding,
> it's
> the importing of submodules. Use any other submodule import spelling to
> make
> it work. This includes
>
> import spam.foo
> from spam.foo import Foo
> __import__('spam.foo')
> importlib.import_module('spam.foo')
>
> 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.
>
> What was the motivation for this? Was the intent really to bind submodule
> names in the parent module seemingly magically?
>
> AFAICT, this also isn't actually documented anywhere. I've looked in the
> Language Reference under the import system[*], and import statement, nor in
> the Library Reference under __import__(). There's lots of material here,
> so I
> could be missing it.
>
> I don't know whether any of the alternative implementations also implement
> this behavior, but they'll have to.
>
> I think this needs to be documented in the Language Reference, and after
> some
> feedback here, I'll open a docs bug and write some text to fix it.
>
It's definitely intentional, and it's fundamental to the package import
design. We've had many implementations of package import (remember "ni.py"?
last seen as "knee.py") and it was always there, because this is done as
part of *submodule loading*. For better or for worse (and because I didn't
know Java at the time :-) Python declares that if you write `import
foo.bar` then later in your code you can use `foo.bar` to reference to the
bar submodule of package foo. And the way this is done is to make each
submodule an attribute of its parent package. This is done when the
submodule is first loaded, and because of the strict separation between
loading and importing, it is done no matter what form of import was used to
load bar.
I guess another thing to realize is that the globals of __init__.py are
also the attribute namespace of the package.
I'm not surprised it's in the reference manual -- that hasn't been updated
thoroughly in ages, and I sometimes cry when I see it. :-) So please do
clarify this for the benefit of future implementers.
--
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/import-sig/attachments/20150422/55def872/attachment-0001.html>
More information about the Import-SIG
mailing list