setup.py中name与py_modules取值不同时模块导入失败如何解决?
问题核心原因
你理解的name和py_modules的功能定位完全正确,二者本来就可以取值不同,出现导入失败的核心原因是源码目录下的模块文件名和py_modules声明的模块名不匹配。
原理说明
setup()的name参数:仅作为包的分发标识使用,和Python运行时的导入逻辑完全无关。你可以理解为这是给pip、PyPI看的名字,和代码运行时没有任何绑定关系。行业内这种分发名和导入名不一致的案例非常普遍,比如分发名为python-dateutil的包,实际导入时用的名字是dateutil。setup()的py_modules参数:用来声明你要打包的顶层模块列表,每个声明的模块名,都需要在package_dir指定的目录下存在同名的.py文件。你配置了py_modules=['importMe']、package_dir={'': 'src'},setuptools就会主动查找src/importMe.py这个文件,如果找不到,就不会把任何模块装入你的虚拟环境,自然会出现导入失败的问题。
修复步骤
- 保持你当前的
setup.py配置不变(分发名installMe,导入模块名importMe) - 将
src目录下你原来的模块文件,重命名为importMe.py(保证文件名和py_modules声明的模块名完全一致) - 卸载之前安装的无效包:
pip uninstall -y installMe
- 重新安装开发版包:
pip install -e .
- 测试导入:此时执行
from importMe import say_hello就可以正常调用,且pip list展示的依然是installMe的分发名,完全满足你要求的二者取值不同的需求。
补充说明
你之所以将name和py_modules设为相同时可以正常运行,是因为此时你src目录下的文件名刚好和name取值(也就是和py_modules的取值)匹配,刚好命中了查找逻辑,并不是因为两个参数必须一致。
另外你尝试导入installMe失败是完全正常的:你没有在setup.py中声明存在名为installMe的模块/包,Python的导入系统自然找不到这个名字。
内容的提问来源于stack exchange,提问作者Michael Emerson
相关产品推荐
相关产品推荐

