setup.py install安装Python包后导入报ModuleNotFoundError本地正常
问题描述
执行python setup.py install安装自研Python包时流程无报错,但安装完成后导入包会触发ModuleNotFoundError,提示找不到对应本地子包;如果切换到包所在目录,在当前目录启动Python解释器执行本地导入,包可以正常运行。
复现过程
项目目录结构如下:
C:. │ setup.py │ └───package │ __init__.py │ └───networking hello.py __init__.py
setup.py文件内容:
from setuptools import setup setup( name="test_package", packages=["package"], version="0.0.1", description="Test", )
package/networking/__init__.py文件内容:
from package.networking.hello import Hello
package/networking/hello.py文件内容:
class Hello: def __init__(self, name): self.name = name def hello(self): print("Hello", self.name)
安装后切换到非项目目录执行导入会报错:
> python setup.py install > cd .. # 切换目录,避免从本地路径导入,强制使用setup.py安装的包版本 > python >>> from package.networking import Hello Traceback (most recent call last): File "<stdin>", line 1, in <module> ModuleNotFoundError: No module named 'package.networking' >>>
在项目同级目录下执行导入可正常运行:
> python >>> from package.networking import Hello >>> Hello("Test").hello() Hello Test
问题原因
setup.py里的packages参数只声明了顶层package包,没有包含子包package.networking,执行安装时setuptools只会把顶层包的文件复制到Python的site-packages目录,子包networking根本没被打包进去,所以跨目录导入时找不到对应模块。
本地运行能成功是因为Python启动时会自动把当前工作目录加入模块搜索路径,能直接读到本地项目里的networking子包文件,和是否正确打包没有关系。
修复方法
两种方案选一个即可:
- 手动补全所有需要打包的子包,修改
setup.py的packages参数,把所有层级的包都列进去:from setuptools import setup setup( name="test_package", packages=["package", "package.networking"], version="0.0.1", description="Test", ) - 用setuptools自带的
find_packages()方法自动扫描项目下所有包,无需手动枚举,后续新增子包也不用修改setup配置,是更通用的方案:from setuptools import setup, find_packages setup( name="test_package", packages=find_packages(), version="0.0.1", description="Test", )
修改完成后重新执行python setup.py install完成安装,再切换到任意目录导入包都可正常运行。
内容的提问来源于stack exchange,提问作者Eric B
相关产品推荐
相关产品推荐

