我偶然发现了一些奇怪的 python (2.7) 导入行为,虽然很容易解决,但让我摸不着头脑。
给定以下文件夹结构:
test/
__init__.py
x.py
package/
__init__.py
x.py
其中 test/package/__init__.py 包含以下内容
from .. import x
print x
from .x import hello
print x
print x.hello
test/package/x.py 包含以下内容
hello = 1
为什么从 REPL 运行 import test.package
会产生以下输出?
<module 'test.x' from 'test/x.pyc'>
<module 'test.package.x' from 'test/package/x.pyc'>
1
我本希望 x
引用顶级 x
模块,但是第二个导入所做的是导入整个本地 x
模块(不仅仅是我预期的 hello
),有效地践踏了第一次导入。
谁能解释一下这里的导入机制吗?
最佳答案
from .x import name
意识到 test.package.x
需要是一个模块。然后它检查 sys.modules 中的相应条目;如果在那里找到它,则 sys.modules['test.package.x'].hello
被导入到调用模块中。
但是,如果 sys.modules['test.package.x']
尚不存在,则会加载该模块;并且加载 sys.modules['test.package'].x
的最后一步被设置为指向新加载的模块,即使您明确没有要求它。因此,第二个导入会覆盖第一个导入的名称。
这是设计使然,否则
import foo.bar.baz
foo.bar.baz.x()
和
from foo.bar import baz
baz.x()
不可互换。
我无法在 Python 2 文档中找到有关此行为的良好文档,但是 Python 3 behaviour在这种情况下本质上是相同的:
When a submodule is loaded using any mechanism (e.g.
importlib
APIs, theimport
orimport
-from
statements, or built-in__import__()
) a binding is placed in the parent module’s namespace to the submodule object. For example, if packagespam
has a submodulefoo
, after importingspam.foo
,spam
will have an attributefoo
which is bound to the submodule.[...]
The invariant holding is that if you have
sys.modules['spam']
andsys.modules['spam.foo']
(as you would after the above import), the latter must appear as thefoo
attribute of the former.
关于python - 来自相关包的未知 python 导入行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29985574/