python模块循环导入问题解析

        在一个包中,如果A的完全导入依赖于B的导入,但是B的完全导入又需要导入A,即两个模块之间存在相互导入,那么就会引发循环导入问题。        

        在python2中,循环导入是不允许的,会直接触发ImportError。但是在python3中,python重写了导入机制,使得循环导入允许发生,但是会存在更隐晦的问题。

        在python3中,只要执行import a后者from . import a,即只要a在import语句之后且被执行,那么a就会被加入到sys.modules中,而后续尽管在模块a被完全执行完毕之前,有模块b导入a,由于a已经在sys.modules中,b会直接从缓存中导入a,而不是重新执行a,因此这时避免了语法上无限循环导入的问题,因此导入语句可以顺利执行。但是由于b导入a时,a可能还没有被完全执行,即a还只是部分执行,所以有些没有被执行到的属性还不存在,那么这时如果b导入a,且调用了a中还没有被执行到的属性,就会触发AttributeError:模块a中缺少如此属性。这便是python3中允许循环导入语法而产生的一个更为隐晦的问题。

        那么如何解决这个问题呢?

1. 重新设计。模块直接存在相互导入,可能存在设计不合理,此时可以merge模块,或者进行更好的抽象;

2. 导入语句只导入相对顶层的模块,不进一步导入子模块,后续在使用的时候通过子模块获取属性;

3. 在需要的时候导入,此时导入可能发生在函数中或者类中,而不是模块顶层,这时就不会在模块被导入时执行,从而可以避免属性不存在问题;

4. 修改初始化文件__init__.py,由于导入包时,实际上在执行该初始化文件,可以剔除非必要初始化,减少顶层模块导入引起的子模块(模块中同时导入了顶层模块)导入。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值