如何为含多模块的独立Python应用正确编写setup.py?
打包与运行问题修复方案
核心问题根源
- 导入语句没有遵循包的绝对导入规则:
aaa是app包的子包,不属于顶级模块,不能直接from aaa...导入 - 开发态运行路径不规范:在
app子目录下直接运行脚本,导致Python搜索路径不包含项目根目录,找不到app包
推荐方案(无需移动原有文件结构)
1. 补充缺失的__init__.py文件
为所有包目录添加空的__init__.py(Python 3.3+虽支持命名空间包,但添加该文件可避免setuptools识别异常),修正后目录结构:
<root> ├─ app | ├─ __init__.py | ├─ aaa | | ├─ __init__.py | | └── module_a.py | ├─ bbb | | ├─ __init__.py | | └── module_b.py | └─ app.py ├─ docs ├─ tests └─ setup.py
2. 修正app.py的导入语句
改为带父包前缀的绝对导入:
#!/usr/bin/python from app.aaa.module_a import method1 from app.bbb.module_b import method2 def main(): print("APP main executed") method1() method2() if __name__ == '__main__': main()
3. 开发态运行方式修正
在app子目录:
python -m app.app
运行输出和原预期完全一致。
若坚持要在
app子目录下直接运行python app.py,可在app.py的导入语句前添加路径修正代码:import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).parent.parent.resolve()))
4. 简化setup.py配置
无需手动列举所有包路径,可使用find_packages自动识别:
from setuptools import setup, find_packages setup( name="app", version="1.0", packages=find_packages(), entry_points={ 'console_scripts': ['app=app.app:main', ] } )
可选方案(将app.py移到根目录的场景)
如果确实要将app.py放在项目根目录,配置方法如下:
- 保持目录结构如你补充说明的版本:
app/__init__.py、app/aaa/__init__.py、app/bbb/__init__.py均存在,根目录有独立app.py - 根目录
app.py的导入语句写为:from app.aaa.module_a import method1 from app.bbb.module_b import method2 setup.py配置:from setuptools import setup, find_packages setup( name="app", version="1.0", packages=find_packages(), # 声明根目录的独立模块app.py py_modules=['app'], # 入口直接指向根目录模块app的main函数 entry_points={ 'console_scripts': ['app=app:main', ] } )
内容的提问来源于stack exchange,提问作者StarterKit
相关产品推荐
相关产品推荐

