Why might Python's `from` form of an import statement bind a module name?

后端 未结 1 1549
耶瑟儿~
耶瑟儿~ 2020-11-27 22:00

I have a Python project with the following structure:

testapp/
├── __init__.py
├── api
│   ├── __init__.py
│   └── utils.py
└── utils.py

Al

相关标签:
1条回答
  • 2020-11-27 22:50

    From the import system documentation:

    When a submodule is loaded using any mechanism (e.g. importlib APIs, the import or import-from statements, or built-in __import__()) a binding is placed in the parent module’s namespace to the submodule object. For example, if package spam has a submodule foo, after importing spam.foo, spam will have an attribute foo which is bound to the submodule. Let’s say you have the following directory structure:

    spam/
        __init__.py
        foo.py
        bar.py
    

    and spam/__init__.py has the following lines in it:

    from .foo import Foo
    from .bar import Bar
    

    then executing the following puts a name binding to foo and bar in the spam module:

    >>> import spam
    >>> spam.foo
    <module 'spam.foo' from '/tmp/imports/spam/foo.py'>
    >>> spam.bar
    <module 'spam.bar' from '/tmp/imports/spam/bar.py'>
    

    Given Python’s familiar name binding rules this might seem surprising, but it’s actually a fundamental feature of the import system. The invariant holding is that if you have sys.modules['spam'] and sys.modules['spam.foo'] (as you would after the above import), the latter must appear as the foo attribute of the former.

    If you do from testapp.api.utils import x, the import statement will not load utils into the local namespace. However, the import machinery will load utils into the testapp.api namespace, to make further imports work right. It just happens that in your case, testapp.api is also the local namespace, so you're getting a surprise.

    0 讨论(0)
提交回复
热议问题