Python 3.7中如何从包内util.py导入__init__.py内容?
解决foo包中util.py访问__init__.py内容的问题
这个错误的根源在于你误解了__init__的含义:当你在util.py中执行from . import __init__时,你导入的并不是__init__.py模块本身,而是当前util.py模块对象的内置__init__方法(这是一个method-wrapper对象),它当然没有你在__init__.py里定义的some_var_in_init属性。
下面是几种可行的解决方法,以及更合理的代码重构建议:
方法1:直接相对导入需要的对象
既然__init__.py里的内容就是foo包的公共属性,你可以直接从包本身相对导入需要的变量、类或函数:
# util.py from . import some_var_in_init # 或者一次性导入多个对象 from . import some_var_in_init, MyClassFromInit, my_function print(some_var_in_init)
方法2:导入整个包模块
如果你需要访问__init__.py里的多个内容,也可以直接导入foo包本身,然后通过包对象访问属性:
# util.py import foo print(foo.some_var_in_init) # 或者用相对导入更符合包内代码规范 from . import foo as foo_package print(foo_package.some_var_in_init)
推荐:代码重构(避免__init__.py臃肿)
随着包的功能扩展,把所有代码都放在__init__.py里会让文件越来越臃肿,不利于维护。推荐的做法是拆分代码到专门的模块中,同时在__init__.py中导出这些内容,保持外部导入的兼容性:
重构后的目录结构
foo/ __init__.py util.py core.py # 存放原来__init__.py中的核心代码
步骤1:迁移代码到core.py
把原来__init__.py里的类、函数、变量移到core.py:
# core.py some_var_in_init = "你的变量值" class MyCoreClass: def __init__(self): pass def my_core_function(): return "核心函数返回值"
步骤2:在__init__.py中导出内容
这样外部用户执行import foo时,依然能访问到原来的内容,保持兼容性:
# __init__.py from .core import some_var_in_init, MyCoreClass, my_core_function
步骤3:在util.py中导入core模块的内容
现在可以直接从core模块导入,代码结构更清晰:
# util.py from .core import some_var_in_init, MyCoreClass print(some_var_in_init)
这种重构方式不仅解决了当前的导入问题,还让包的结构更合理,便于后续扩展和维护。
内容的提问来源于stack exchange,提问作者Al Sweigart




