Python项目迁移后遇AttributeError:b4.storage模块无b4_storage属性
Python 2.7迁移至3.12后出现
AttributeError: module 'b4.storage' has no attribute 'b4_storage' 项目结构
b4 \storage __init__.py b4_common.py b4_mysql.py b4_storage.py __init__.py b4_run.py
报错情况
运行python b4_run.py时触发错误:
AttributeError: module 'b4.storage' has no attribute 'b4_storage'
PyCharm可正常识别b4.storage.b4_storage.Storage路径,且Storage类确实定义在b4_storage.py中。此前因循环引用问题,采用直接导入而非from {file} import {class}的方式,解决循环引用后出现该问题。
已尝试的方案
- 重命名
b4_storage.py为b4_dbstorage.py,报错变为AttributeError: module 'b4.storage' has no attribute 'b4_dbstorage' - 将
b4_storage.py内容合并到b4_common.py,但b4_mysql.py出现类似报错
报错代码位置
报错发生在b4_common.py的以下代码行:
import b4.storage.b4_storage class DatabaseStorage(b4.storage.b4_storage.Storage):
报错回溯信息
File "/usr/lib/python3.10/runpy.py", line 187, in _run_module_as_main mod_name, mod_spec, code = _get_module_details(mod_name, _Error) File "/usr/lib/python3.10/runpy.py", line 110, in _get_module_details __import__(pkg_name) File "/usr/local/lib/python3.10/dist-packages/b4-0.2-py3.10.egg/b4/b4_run.py", line 25, in <module> import b4 File "/usr/local/lib/python3.10/dist-packages/b4-0.2-py3.10.egg/b4/__init__.py", line 34, in <module> import b4.b4_config File "/usr/local/lib/python3.10/dist-packages/b4-0.2-py3.10.egg/b4/b4_config.py", line 33, in <module> import b4.storage.b4_storage File "/usr/local/lib/python3.10/dist-packages/b4-0.2-py3.10.egg/b4/storage/b4_storage.py", line 26, in <module> import b4.storage.b4_mysql File "/usr/local/lib/python3.10/dist-packages/b4-0.2-py3.10.egg/b4/storage/b4_mysql.py", line 26, in <module> import b4.storage.b4_common File "/usr/local/lib/python3.10/dist-packages/b4-0.2-py3.10.egg/b4/storage/b4_common.py", line 39, in <module> class DatabaseStorage(b4.storage.b4_storage.Storage): AttributeError: module 'b4.storage' has no attribute 'b4_storage'
问题原因及解决方法
这是循环导入导致的模块加载未完成问题,从回溯能看到完整加载链:b4_run.py → b4 → b4_config → b4.storage.b4_storage → b4.storage.b4_mysql → b4.storage.b4_common → 尝试访问b4.storage.b4_storage
此时b4_storage模块还在加载过程中,并未完成注册到b4.storage命名空间的操作,所以通过父命名空间访问会失败。
解决方法1:修改导入方式,直接引用模块别名
把b4_common.py中的代码改成:
import b4.storage.b4_storage as b4_storage class DatabaseStorage(b4_storage.Storage):
直接使用导入的模块别名,绕开父命名空间的访问限制。
解决方法2:延迟导入(适用于非继承场景)
如果循环导入无法避免,将导入操作放到函数内部(而非模块顶层):
class DatabaseStorage: def __init__(self): import b4.storage.b4_storage self.base_storage = b4.storage.b4_storage.Storage()
注意:该方法不适用于类继承的场景,因此优先推荐方法1。
解决方法3:彻底清理循环依赖
重构代码,把循环依赖的公共逻辑抽离到独立模块(比如新增b4_base.py),消除模块间的循环引用,从根源解决问题。
内容的提问来源于stack exchange,提问作者isopropanol
相关产品推荐
相关产品推荐

