Python循环引用是允许的,但在极端情况下仍然会挂挂。比如:
a.py
import sys
print("a,start")
for item in sys.modules:
if item in ["a", "b"]:
print(item)
from b import c
def start():
pass
b.py
import sys
print("b start")
for item in sys.modules:
if item in ["a", "b"]:
print(item)
from a import start
def c():
pass
结果:
a,start
b start
b
Traceback (most recent call last):
File "E:/yinzihao/workspace/testpy/a.py", line 6, in <module>
from b import c
File "E:\yinzihao\workspace\testpy\b.py", line 7, in <module>
from a import start
File "E:\yinzihao\workspace\testpy\a.py", line 6, in <module>
from b import c
ImportError: cannot import name 'c'
a,start
b
a
1.检查sys.modules中是否有这个模块 2.如果没有,将sys.modules[module] = empty_pyc 3.执行module.py的所有代码,生成对应的pyc 4.sys.modules[module] = real_pyc
1.首先执行 a:from b import c
2.此时sys.modules中没有b(也没有a),跳转到b.py。将b 添加到sys.modules。
3.执行 b:from a import start
4.此时sys.modules中没有a,跳转到a.py,将a添加到sys.modules。此时,a,b都在sys.modules中。
5.程序再次执行到 a:from b import c
。此时sys.modules中包含b,所以,会直接尝试加载b.c
,然而,b并没有执行完全,c是不存在的。
几乎所有的循环引用BUG都是直接使用from aa import bb
造成的。使用import aa
,再在代码中使用aa.bb
可以避免大部分异常。