【发布时间】:2019-10-12 02:14:34
【问题描述】:
循环导入的行为是否在 Python 中明确指定,还是只是特定于实现?
例如在 cpython 中,导入子模块会导致子模块被分配为父模块的属性,但直到子模块完成执行之后。这在文档或 PEP 的任何地方都有说明吗?
通常情况下,python 循环导入只是起作用(在导入期间不执行任何函数等约定的辅助,并以与预期调用顺序相反的方式布置源代码以定义函数),但上述行为的结果是您不能通过父级引用部分导入的模块。例如,如果导入package.submodule 会导致导入othermodule,那么othermodule 不能执行import package.submodule as submod,但可以 执行from package import submodule as submod。这是由文档解释/指定的吗?如果不是,它可能会改变吗?
在这种情况下,差异是因为 import package.submodule as submod 被实现为对 __import__ 的调用(返回 package),然后是属性查找(检索 submodule 以便可以将其分配给 @987654331 @)。相反,from package import submodule as submod 导致__import__ 直接返回submodule(即使submodule 仍然只完成了一半,这似乎也有效)。如果您深入研究 cpython 字节码(记录在标准库的 dis 部分中)并研究 __import__ 语义,您可以弄清楚其中的一些。但是,由于解决循环导入是 python 中的一个常见问题,因此找到一个官方的高级摘要来说明预期会有什么用处?
例子:
mkdir package
touch package/__init__.py
cat > package/submodule.py << EOF
def f():
print('OK')
import othermodule
othermodule.g()
def notyetdefined():
pass
EOF
cat > othermodule.py << EOF
def g():
try:
import package.submodule as submod # this fails
except AttributeError:
print('FAIL')
from package import submodule as submod # this works ok
submod.f()
#submod.notyetdefined() # this cannot be invoked
EOF
python -c 'import package.submodule'
python 3.6.7 中的输出:
FAIL
OK
【问题讨论】:
-
This question 是相关的,但是,虽然答案确实涉及循环导入的行为,但他们没有说明它是否是规范的一部分。我自己的假设(我相信其他问题的一些答案也支持这一点)是,导入的明确定义的行为通常会导致一致,即使它没有明确记录。
-
另外值得注意的是,这仅在 Python 3.7 和 3.8 中打印“OK”。
标签: python python-3.x documentation python-import circular-dependency