关于python循环调用的问题

错误: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引入和判定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值