You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何需在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:26:41