Python 模块加载机制导致的问题

Python 在导入模块时,会执行模块中的代码。当存在互相依赖(循环依赖)时,如果在模块顶层进行导入,可能会出现问题。因为在一个模块还未完全加载和初始化时,另一个模块就尝试导入它,这可能会导致某些对象或属性还未定义。

module_a.py

from module_b import B

class A:
    def __init__(self):
        self.b = B()

a = A()

module_b.py

from module_a import A

class B:
    def __init__(self):
        self.a = A()

b = B()

当 Python 解释器执行 import module_a 时,会先执行 module_a.py 中的代码。在执行到 from module_b import B 时,会去加载 module_b.py。而 module_b.py 中又有 from module_a import A,此时 module_a 还未完全加载完毕,A 类可能还未定义,就会导致循环依赖错误。

函数内导入的延迟加载特性
将导入语句放在函数内部,导入操作会延迟到函数被调用时才执行。这样就避免了在模块加载阶段就出现循环依赖的问题。

module_a.py

class A:
    def __init__(self):
        from module_b import B
        self.b = B()

a = A()

module_b.py

class B:
    def __init__(self):
        from module_a import A
        self.a = A()

b = B()

在这个修改后的例子中,当 module_a.py 被加载时,并不会立即执行 from module_b import B,而是在 A 类的 init 方法被调用时才执行。同理,module_b.py 中的导入操作也是延迟执行的。这样,每个模块在加载时都不会尝试去导入还未完全加载的模块,从而避免了循环依赖问题

注意事项

虽然将导入语句放在函数内部可以解决循环依赖问题,但这可能会影响代码的可读性和性能。因为每次调用函数时都会执行导入操作,可能会带来一些额外的开销。更好的做法是重构代码,避免循环依赖的产生。

pydeps

https://knowledge.zhaoweiguo.com/build/html/lang/pythons/tools/code_analysis/pydeps
https://pypi.org/project/pydeps/

brew install graphviz
pip install pydeps
pydeps xx.py --show-deps

会用图的方式检测出互相依赖

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值