gpt4 book ai didi

python - 为什么 Python 的 `from` 形式的 import 语句会绑定(bind)模块名称?

转载 作者:IT老高 更新时间:2023-10-28 20:29:12 27 4
gpt4 key购买 nike

我有一个 Python 项目,其结构如下:

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

所有模块都是空的,除了 testapp/api/__init__.py 有以下代码:

from testapp import utils

print "a", utils

from testapp.api.utils import x

print "b", utils

和定义xtestapp/api/utils.py:

x = 1

现在我从根目录导入 testapp.api:

$ export PYTHONPATH=$PYTHONPATH:.
$ python -c "import testapp.api"
a <module 'testapp.utils' from 'testapp/utils.pyc'>
b <module 'testapp.api.utils' from 'testapp/api/utils.pyc'>

导入的结果让我吃惊,因为它表明第二个import 语句已经覆盖了utils。然而文档指出 from statement will not bind a module name :

The from form does not bind the module name: it goes through the list of identifiers, looks each one of them up in the module found in step (1), and binds the name in the local namespace to the object thus found.

确实,当我在终端中使用 from ... import ... 语句时,不会引入任何模块名称:

>>> from os.path import abspath
>>> path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined

我怀疑这与 Python 有关,在第二个导入语句时,尝试导入引用 testapp.utilstestapp.api.utils 和失败,但我不确定。

这里发生了什么?

最佳答案

来自 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.

如果您执行 from testapp.api.utils import x,import 语句不会将 utils 加载到本地命名空间中。但是,导入机制会将 utils 加载到 testapp.api 命名空间中,以使进一步的导入正常工作。碰巧在您的情况下, testapp.api 也是本地命名空间,所以您会感到惊讶。

关于python - 为什么 Python 的 `from` 形式的 import 语句会绑定(bind)模块名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29974455/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com