python循环引用中的原理 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 from b import c File "E:\yinzihao\workspace\testpy\b.py", line 7, in from a import start File "E:\yinzihao\workspace\testpy\a.py", line 6, in from b import c ImportError: cannot import name 'c' a,start b a ``` 原理很简单,python中import module会执行以下几步: 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`可以避免大部分异常。 来自 大脸猫 写于 2018-07-05 00:47 -- 更新于2020-10-19 13:06 -- 0 条评论