Python导入模块报错AttributeError: module 'lib' has no attribute 'subpackage'求助
解决Python模块初始化时的
AttributeError: module 'lib' has no attribute 'subpackage'问题 这个报错是典型的模块初始化顺序冲突导致的,咱们先一步步拆解问题根源,再给出可行的解决办法。
问题根源分析
先理清楚你的代码执行时的导入流程:
- 运行
main.py,执行import lib.subpackage - Python先加载空的
lib/__init__.py,创建lib模块对象;接着开始加载lib/subpackage/__init__.py,创建lib.subpackage模块对象(注意:此时这个模块对象还在初始化中,还没被添加到lib模块的属性列表里) subpackage/__init__.py先执行import lib.subpackage.sched——这一步没问题,因为lib.subpackage对象已经存在,只是在初始化;接着执行import lib.subpackage.app- 加载
app.py时,执行import lib.subpackage.sched as foo——这里尝试通过lib.subpackage去访问sched,但此时lib模块里还没有subpackage这个属性(因为lib.subpackage还在初始化过程中,没完成注册),所以直接抛出了AttributeError。
简单说:你在子模块里用绝对导入访问父包的子模块时,父包还没来得及把当前子包注册为自己的属性,导致找不到。
解决办法
方法1:使用相对导入(最推荐)
把所有子包内部的导入改成相对路径,这样不依赖父包的属性注册,直接基于当前包定位模块:
修改lib/subpackage/__init__.py:
from . import sched from . import app
修改lib/subpackage/app.py:
from . import sched as foo
这样导入时直接基于当前的subpackage包操作,完全绕开了lib模块是否已经注册subpackage属性的问题,初始化顺序也不会再冲突。
方法2:延迟导入(适合非模块级别的依赖)
如果app.py里的sched模块不是在模块加载时就需要,而是在某个函数里才用到,可以把导入语句移到函数内部:
修改lib/subpackage/app.py:
def some_function(): import lib.subpackage.sched as foo # 在这里使用foo
这样模块初始化时不会触发导入,等到函数执行时,lib.subpackage已经完成初始化并注册到lib模块里了,就不会报错。不过这种方法只适合非模块级的依赖场景。
方法3:调整导入顺序(不推荐,容易出问题)
如果你坚持用绝对导入,可以尝试调整subpackage/__init__.py的导入顺序,先导入所有不需要依赖其他子模块的文件,再导入依赖的:
修改lib/subpackage/__init__.py:
# 先导入sched(空文件,无依赖) import lib.subpackage.sched # 再导入app,此时sched已经被导入,lib.subpackage也更接近初始化完成 import lib.subpackage.app
不过这种方法依赖Python的初始化细节,不同版本可能有差异,而且后续代码变动很容易再次触发问题,所以不推荐。
验证
修改后重新运行main.py,应该就能正常执行了。
内容的提问来源于stack exchange,提问作者Stefan Monov
相关产品推荐
相关产品推荐

