Python 3.6.4虚拟环境中命名空间包安装目录结构异常问题
解决Python 3.6.4中PEP 420命名空间包目录结构异常问题
我之前在维护跨版本Python的命名空间包时,也碰到过Python 3.6.4这个版本的目录结构问题——毕竟PEP 420的隐式命名空间包在早期Python 3版本里的支持确实有点坑,结合你描述的情况,咱们一步步来解决:
问题根源拆解
你的Python 2.7环境用pkgutils风格能正常工作,是因为它依赖__init__.py里的__import__('pkg_resources').declare_namespace(__name__)来声明命名空间;但PEP 420的隐式命名空间包不需要这种声明,且对目录结构、工具链版本有更严格的要求,而Python 3.6.4默认配套的pip/setuptools版本对PEP 420的支持不够完善,这是核心问题。
解决方案步骤
1. 调整包目录结构以符合PEP 420要求
- 命名空间根目录
tools绝对不能包含__init__.py——这是隐式命名空间包的关键标识,如果加了这个文件,Python会把它当作普通包而非命名空间,直接导致目录结构异常。 - 子包
tools/sub_a可以保留自己的__init__.py,这个不影响命名空间的识别,你原来的name='sub_a'配置可以保留。
2. 修正setup.py的配置逻辑
要使用setuptools提供的find_namespace_packages()来自动识别命名空间包,而不是手动指定packages列表,示例配置如下:
from setuptools import setup, find_namespace_packages with open("README.rst", "r") as fh: long_description = fh.read() setup( name="tools-sub-a", # 注意命名要唯一,避免和其他命名空间包冲突 version="0.1.0", author="Your Name", description="Sub package under tools namespace", long_description=long_description, long_description_content_type="text/x-rst", packages=find_namespace_packages(include=["tools.*"]), # 仅包含tools下的子包 # 其他配置(如install_requires等)按需添加 )
如果你的setuptools版本太旧没有find_namespace_packages(),先执行升级(见下一步)。
3. 升级pip和setuptools到兼容版本
Python 3.6.4默认的pip(通常是9.x或10.x)和setuptools版本对PEP 420的支持有缺陷,必须升级到更稳定的版本:
pip install --upgrade pip setuptools
升级完成后,先卸载之前安装的旧包(避免缓存干扰):
pip uninstall -y tools-sub-a
然后重新安装你的包:
pip install .
4. 验证安装结果
安装完成后,去你的虚拟环境venv/Lib/site-packages目录下查看:
- 应该存在
tools/目录(无__init__.py),里面包含sub_a/子目录(带你原来的__init__.py和module.py) - 同时会生成
tools_sub_a-<version>.dist-info的元数据目录,这是每个独立命名空间子包的正确元数据存储方式。
额外注意事项
- 如果后续要添加同命名空间的其他子包(比如
tools/sub_b),只需遵循同样的结构和配置,安装后tools目录会自动合并所有子包。 - 不要在
tools目录下添加任何其他文件或目录,避免干扰命名空间的识别。
内容的提问来源于stack exchange,提问作者Matt_G
相关产品推荐
相关产品推荐

