Python自定义包安装后导入子包触发ModuleNotFoundError的解决办法
解决Python包本地开发与安装后导入兼容问题
问题背景
你创建了包含多子包的Python包,本地运行源码正常,但通过pip安装到虚拟环境后,运行CLI入口点时出现ModuleNotFoundError: No module named subpackage1;修改导入语句为from mypackage.subpackage1.module1 import foo后,安装包可正常运行,但本地开发环境又报错。
核心原因
- 本地运行时,项目根目录在Python路径中,直接写
subpackage1能被识别;但安装后,包以mypackage为顶层模块存在于site-packages,此时直接导入subpackage1会被当作顶层模块查找,自然找不到。 - 你在
pyproject.toml中存在拼写错误:将包名mypackage写成了maypackage,这会导致入口点无法正确定位模块。
解决方案
方案1:使用相对导入+规范运行方式
修改entrypoint.py的导入语句为相对导入(适合包内部模块间的引用):
from .subpackage1.module1 import foo from .subpackage2.module2 import baz if __name__ == "__main__": pass
- 本地测试时,不能直接运行
python entrypoint.py,需通过包模块方式启动:python -m mypackage.entrypoint - 修正
pyproject.toml的拼写错误,配置正确的入口点:[project.scripts] mypackage-cli = "mypackage.entrypoint:__main__"
方案2:绝对导入+本地可编辑安装(推荐)
这种方式能让本地开发和安装后的导入逻辑完全一致:
- 修改
entrypoint.py为绝对导入:from mypackage.subpackage1.module1 import foo from mypackage.subpackage2.module2 import baz def main(): # 这里编写CLI的核心逻辑 pass if __name__ == "__main__": main() - 修正
pyproject.toml的拼写错误并配置入口点到main函数:[project.scripts] mypackage-cli = "mypackage.entrypoint:main" - 本地开发时,安装可编辑版本的包:
这会让Python自动将项目根目录加入路径,本地运行pip install -e .mypackage-cli或直接执行模块都不会报错,同时安装后的包也能正常工作。
补充说明
空的__init__.py文件是没问题的,不需要额外配置路径,Python 3.3+支持命名空间包,但这里的结构是常规包,空__init__.py足够。
内容的提问来源于stack exchange,提问作者devnectar
相关产品推荐
相关产品推荐

