写在前面
还是前段时间写的那个敏感信息提取框架工具的时候,没错,又犯了一个低级错误,python的循环调用,在此简单记录一下。
Python循环调用原理
先简单说一下什么是循环调用?
现在有一个文件a.py,有一个test_a的函数
def
test_a
()
:
pass
又有一个文件b.py,有一个test_b的函数
def
test_b
()
:
pass
这么写是没问题的,那么假如a.py中import了b.py中的test_b,同时b.py中又引用了a.py中的test_a,如下
# a.py
from
b
import
test_b
def
test_a
()
:
pass
# b.py
from
a
import
test_a
def
test_b
()
:
pass
这个时候假如在主程序中对其中一个文件进行调用,就会出现无法跳出的调用循环:执行a.py时,去调用b.py,调用到b.py进行执行的时候又调用到a.py,针对这种情况,python解释器会直接抛出异常。
实际案例
上述例子过于简单,所以大家可能没什么感受。但是在项目文件稍微多一些时,确实容易在复杂的环境下出现这种循环调用的问题,比如我的这次坑。
我写了一个分类器类A存放在一个py文件中,这个类会根据不同的文件类型去创建不同的文件处理器对象。而其中的一个文件处理器对象就是需要二次分类的,即需要调用分类器类A进行二次分类,这就出现了循环调用,你中有我、我中有你。
破局
那么针对这种情况怎么破局呢?
回到最开始那个简单的案例中,他们的调用逻辑都是a.py的第一行调用到b.py的第一行,b.py的第一行又调用到a.py的第一行。
那么想要破局其实很简单,让程序能够往下走就行了,不要缠绕在最初import的那块区域。
即:可能存在循环调用的时候,不在最开始进行import,而是在代码中实际用到的时候再进行import
# a.py
from
b
import
test_b
def
test_a
()
:
print(
1
)
if
__name__ ==
"__main__"
:
test_b()
# b.py
def
test_b
()
:
if
True
:
from
a
import
test_a
test_a()
pass
大家可以尝试一下,在同一目录下创建a.py,b.py这两个文件,发现是可以正常执行的
为什么呢?大家可以分析一下程序的调用过程
- 在a.py对b.py进行调用的时候,直接返回了test_b()的函数,这个过程是不会对函数体进行执行的
- 然后调用test_b()函数的时候,又对a中的test_a()进行调用,调用回去了
- 回到a.py,继续重复第一步,又接着向下执行返回test_a给到b.py中
- b.py调用test_a()
- 打印1,执行结束
肯定会进行一次重复调用,但是调用完之后程序会向下执行,所以就完美地解决了这个问题。
当然,这只是缓兵之计,最好的办法还是设计好项目结构,不要出现这种情况,毕竟还得多调用一次。
原文始发于微信公众号(飞羽技术工坊):Python循环调用破局之法
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论