为何需在setup.py中包含Python子包?基于mltester包场景
为什么setup.py需要包含子包?
嘿,这个问题问到点子上了!咱们先拆解下本地运行(比如你在Eclipse里的情况)和打包分发的核心差异,你就能瞬间明白原因啦:
1. 本地运行为啥没问题?
在Eclipse里直接运行时,Python解释器是直接读取你项目目录里的文件——你的mltester目录在Python的sys.path里,而且你在__init__.py里导入了actions、dialogs和ml_tester,同时ml_tester.py里也直接导入了子包内容,所以解释器能顺利找到所有模块,运行自然没问题。
2. 打包分发时为啥必须声明子包?
当你用setup.py打包你的包(比如生成.whl或.tar.gz),或者把包上传到PyPI让别人安装时,setuptools不会自动递归包含所有子目录。它需要你明确告诉它:哪些目录属于这个包的一部分。
如果不在setup.py里声明actions和dialogs这两个子包,那打包出来的安装包只会包含mltester/__init__.py和mltester/ml_tester.py,子包的文件会被完全忽略。这时候别人安装你的包后,运行代码时就会抛出ModuleNotFoundError,找不到actions或dialogs模块。
正确的setup.py写法示例
你可以用两种方式声明子包:
- 自动查找所有子包(推荐):
from setuptools import setup, find_packages setup( name="mltester", version="0.1", packages=find_packages(), # 自动找到mltester及其所有子包 ) - 手动列出所有包:
from setuptools import setup setup( name="mltester", version="0.1", packages=["mltester", "mltester.actions", "mltester.dialogs"], )
小补充:关于__init__.py的导入优化
顺便提一句,你当前__init__.py里的import actions其实是绝对导入的写法,在包内部更推荐用相对导入,比如:
from . import actions from . import dialogs from . import ml_tester
这样能避免和全局环境里的同名模块冲突,让包的结构更严谨。
内容的提问来源于stack exchange,提问作者Elad Weiss
相关产品推荐
相关产品推荐

