如何使用setup.py将根目录下的子模块纳入foo包命名空间
问题原因
- 传统可编辑安装(
pip install -e .)的实现逻辑是将项目根目录添加到Python的模块搜索路径中,不会像普通安装一样把包文件复制到site-packages目录,因此不会处理package_dir中配置的虚拟路径映射。 - 你的项目中
baz/目录实际不在foo/目录下,Python搜索foo.baz模块时只会在物理存在的foo/目录下查找子目录,自然找不到对应模块。普通安装因为直接把baz/的内容复制到了安装目录的foo/baz/路径下,所以可以正常导入。 - 这个是setuptools传统可编辑模式的已知限制,并非pip的bug。
解决方案
方案一:调整目录结构(兼容性最高,最稳妥)
把baz/目录移动到foo/目录下,调整后的目录结构为:
foo/ ├─ bar/ │ ├─ __init__.py ├─ baz/ │ ├─ __init__.py ├─ __init__.py setup.py
修改setup.py移除package_dir配置即可:
from setuptools import setup setup(name='Foo', version='1.0', description='Test Package', namespace_packages = ['foo'], packages = ['foo.bar', 'foo.baz'], include_package_data = True, )
方案二:保留现有目录结构,使用PEP 660标准的可编辑安装
如果不想调整目录结构,可以使用新版本setuptools支持的符合PEP 660的可编辑安装模式,操作步骤如下:
- 项目根目录新增
pyproject.toml文件,指定构建后端依赖:
[build-system] requires = ["setuptools>=64.0.0", "wheel"] build-backend = "setuptools.build_meta"
- 修改setup.py,替换导入源并补全目录映射配置:
from setuptools import setup setup(name='Foo', version='1.0', description='Test Package', namespace_packages = ['foo'], packages = ['foo', 'foo.bar', 'foo.baz'], package_dir = { "foo": "foo", "foo.baz": "baz", }, include_package_data = True, )
- 升级本地工具链后重新执行可编辑安装:
pip install --upgrade pip setuptools wheel pip install -e .
内容的提问来源于stack exchange,提问作者DurandA
相关产品推荐
相关产品推荐

