概述
错误:ImportError: cannot import name 'a' from partially initialized module 'B' (most likely due to a circular import)
借用其他博客的一段话
循环引用
import执行过程,发生的原因
当我们import一个文件时,python会首先去查找这个文件之前是否被import过,如果这个文件之前有被import过,就不会重新再import一次。所以如果A模块
代码里import了B模块,并且B模块里又import了A模块,python的执行顺序会变成这样:
- 开始执行模块A
- 当A执行到import B的地方,则停止执行A模块后面的代码,转而开始执行B模块的代码
- 当B模块从头执行到import A的地方时,python此时并不会回过头去接着执行A剩余的代码,是重新执行代码,而且将B模块在中断前已经初始化的属性全加载到A模块中
也就是说有两点相当重要:
1.每次import都是从第一行执行代码,即使你只import了B中的一个变量或者函数,还是会执行完所有代码。
2、例外:在模块栈内出现了如下A import B import A时,也就是A->B->A,如下图,如果出现这种情况,python会认为可能马上要出现循环调用了,此时在第二个A的位置如果还要import B会直接import B的已经加载好的模块,也就是引入上面标红的B,而不会再去从头执行B的第一行,如果此时A要import的是B还未加载好的变量或者函数等等时就会报错(不报错的话会形成A->B->A->B的死循环,无法结束),如果import的是加载好的变量或者函数则可以打破循环正常执行。
如下图所示的模块栈就有可能发生循环引用
可以看看下面的例子
A.py
import sys
a=8
from B import a
print(__name__)
c=8
print(a)
B.py
b=4
print('testMoudel:'+__name__)
import A
print(A.a)
a=3
我们使用A作为入口,依赖链是这样的
A->B.a表示A依赖B.a
A->B.a,B->A
步骤:
执行A文件,到这一步import
可以看到目前栈里有一个A,右侧a=8是已经加载好的参数,此时还有一个参数c未加载,此时要跳转到B的第一行了。
跳转执行到B的做这一行
可以看到模块B入栈,有一个已加载好的参数b=4,此时还有一个参数a未加载,此时要跳转到A的第一行了。
再跳转执行到A的import语句, 此时新的模块A入栈,但此时已经达成A->B->A的形式了,我再次执行
from B import a
这时python已经察觉了可能会发生循环调用,所以这里import会使用上一个已经加载的B模块,这个B模块有一个已加载好的参数b=4,此时还有一个参数a未加载,但我要从B里import a,这里python就会直接报错,因为如果再去执行B的第一行会陷入无限的循环,python察觉到了这一点,所以直接报错了,如果import的是B的变量b则不会报错,程序可以正常运行。
同理也适用于
A->B->C->A,到最后一个A时会引入已加载好的B
A->A,到最后一个A是会引入已经加载好的A
也就是链中的第一个重复地模块出现时会出现特殊的import引入和判定。
最后
以上就是外向招牌为你收集整理的关于python循环调用的问题import执行过程,发生的原因的全部内容,希望文章能够帮你解决关于python循环调用的问题import执行过程,发生的原因所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复