我在代码中找到了一个奇怪的循环引用,这是最小代码:
ph
|-- mod
| |-- __init__.py
| |-- pkg.py # import mod.sub_mod.sub_pkg
| `-- sub_mod
| |-- __init__.py
| `-- sub_pkg.py # from mod import pkg
`-- main.py
mod
中的,只有pkg.py
和sub_pkg.py
包含文件内容。
在main.py
:
import mod.pkg
会导致ImportError
,但
import mod.sub_mod.sub_pkg
效果很好。
当我试图找到这个最小的可重现的例子时,我发现在python 3中,两个导入都可以工作。 我也找到了这个页面:https://gist.github.com/datagrok/40bf84d5870c41a77dc6但我还是不知道为什么。
答案 0 :(得分:1)
如果您使用import mod.pkg
开始循环导入,则先mod/pkg.py
启动,然后尝试import mod.sub_mod.sub_pkg
。 mod/sub_mod/sub_pkg.py
启动,并尝试运行from mod import pkg
,但mod.pkg
模块已初始化。
Python跳过尝试从pkg
模块对象中检索mod
属性。但是,在mod.pkg
模块完成初始化之前,该属性不会设置,因此from mod import pkg
会失败。
如果您使用import mod.sub_mod.sub_pkg
开始循环导入,则先mod/sub_mod/sub_pkg.py
启动,然后尝试运行from mod import pkg
。 mod/pkg.py
启动,然后尝试import mod.sub_mod.sub_pkg
。 mod.sub_mod.sub_pkg
模块已经初始化,但Python此次没有尝试访问属性。
from mod import pkg
需要从pkg
检索mod
属性,因为它需要将该属性的值绑定到本地命名空间中的名称pkg
。但是,import mod.sub_mod.sub_pkg
仅绑定本地名称空间中的mod
名称。 Python将mod
名称绑定到mod
模块命名空间中的mod.pkg
模块并继续。
在Python 3中,在第一种情况下,当from mod import pkg
无法在pkg
上找到mod
属性时,会出现回退。 Python检查sys.modules
dict以查找'mod.pkg'
的条目,找到一个,并将找到的模块绑定到pkg
名称。