共享顶级模块的多包混合可编辑安装时导入报错如何解决?
问题原因
该问题由Python包导入规则和命名空间包的特性导致:
- 普通安装lib1、lib2时,两个包的
top.lib1、top.lib2模块会被放到site-packages的同个top目录下,导入时可以正常识别。 - 当其中一个包以
-e可编辑模式安装时,pip会将该包的源码路径加入sys.path。Python导入top模块时会优先匹配到可编辑安装的包下的top目录,而该目录下的__init__.py会让Python将其识别为普通单目录包,不会再去其他路径(比如site-packages)下的top目录查找子模块,因此找不到另一个包的子模块。
可行解决方案
方案1:使用Python3.3+隐式命名空间包(最推荐)
直接删除两个包中top目录下的__init__.py文件,即删除:
lib1/top/__init__.pylib2/top/__init__.py
不需要修改setup.py的配置,Python会自动将top识别为隐式命名空间包,遍历所有sys.path路径下的top目录查找子模块,不管是普通安装还是可编辑安装都能正常导入。
方案2:使用pkg_resources显式命名空间包(兼容旧版本Python)
如果需要保留top目录下的__init__.py,可以按如下配置:
- 在两个包的
top/__init__.py中都添加如下代码:
__import__('pkg_resources').declare_namespace(__name__)
- 在两个包的
setup.py的setup参数中新增命名空间声明:
setup( # 原有其他配置不变 namespace_packages=['top'] )
配置完成后重新安装即可正常使用。
方案3:本地开发临时方案
如果不想修改包配置,仅在本地开发时使用,可以将两个包都以可编辑模式安装:
pip install -e ./lib1 -e ./lib2
此时两个包的源码路径都会加入sys.path,Python可以正常找到两个子模块,但该方案不适合正式发布场景。
内容的提问来源于stack exchange,提问作者Tyilo
相关产品推荐
相关产品推荐

