如何将__main__.py作为Python模块入口实现常规导入?
问题描述
文件结构如下:
parent_folder ├── caller.py └── app ├── script_1.py ├── script_2.py └── __main__.py
__main__.py作为app模块的入口文件,代码如下:
# __main__.py from app.script_1 import MyClassB from app.script_2 import MyClassC class MyClassA: def __init__(self): print('This instanciate a MyClassA object') def func_a(): print('Some Function')
caller.py的代码:
# caller.py import app app.func_a() obj_a = app.MyClassA()
在Windows 10的Python 3.8.10环境下运行python caller.py时,出现报错:
Traceback (most recent call last): File "caller.py", line 2, in <module> app.func_a() AttributeError: module 'app' has no attribute 'func_a'
已知修改caller.py为import app.__main__ as app可正常运行,但这种方式不符合常规模块导入习惯,请问如何才能将__main__.py作为模块入口实现常规导入?
解决方案
Python中import app时,实际导入的是app模块的__init__.py文件(若存在),而非__main__.py。__main__.py的作用是当用python -m app直接运行模块时作为入口,或模块被当作脚本执行时使用,但它不会自动成为app模块的公开接口一部分。要实现常规import app就能访问相关内容,有两种常用方法:
方法1:创建__init__.py导入__main__内容
在app文件夹下创建__init__.py文件,内容如下:
# app/__init__.py from .__main__ import MyClassA, func_a
这样import app时,app模块会自动将__main__.py里的MyClassA和func_a导入自身命名空间,caller.py无需修改即可正常调用。
方法2:分离核心代码与入口逻辑(更规范)
把__main__.py中的核心代码迁移到单独模块,再让__init__.py和__main__.py分别导入:
- 在app文件夹下创建
core.py:
# app/core.py from app.script_1 import MyClassB from app.script_2 import MyClassC class MyClassA: def __init__(self): print('This instanciate a MyClassA object') def func_a(): print('Some Function')
- 修改
app/__init__.py:
# app/__init__.py from .core import MyClassA, func_a
- 修改
app/__main__.py(保留模块直接运行的入口功能):
# app/__main__.py from .core import * # 可添加模块直接运行时的逻辑,比如: if __name__ == '__main__': func_a() obj_a = MyClassA()
这种方式符合Python模块设计规范,分离核心代码与入口逻辑,便于后续维护和扩展。
内容的提问来源于stack exchange,提问作者Alexandre de Castro Maciel
相关产品推荐
相关产品推荐

