Python相对导入自定义模块报无已知父包ImportError问题咨询
你遇到的ImportError: attempted relative import with no known parent package和是否添加__init__.py无直接关联。只要你直接以单文件脚本形式运行sim/out/main.py,Python就会将其识别为顶层入口模块(__name__ = "__main__"),不存在任何父包上下文,你写的三层相对导入from ...libs import plus根本没有可以参照的父包层级,必然报错。
补充说明:你写的导入语句层级数本身是正确的——三个点代表向上回溯两层父包,刚好对应Project根目录,和libs包的位置匹配。你之前给所有包目录加空__init__.py的操作是符合包规范的,只是没有解决运行入口的识别问题。
方案1:以模块模式运行入口(最符合Python包设计规范,推荐)
相对导入仅在模块作为包的一部分被加载时才能生效,你需要停止直接运行main.py文件本身,改用Python的-m参数以模块方式启动:
- 打开终端,进入
Project文件夹的上级目录 - 执行启动命令:
python -m Project.sim.out.main
执行该命令时,Python会自动按照包层级检索模块,给main.py注入正确的__package__属性(值为Project.sim.out),相对导入可以正常解析。
如果需要在VSCode中实现一键运行,直接在工作区的.vscode/launch.json中添加如下配置即可:
{ "version": "0.2.0", "configurations": [ { "name": "Python: 运行主模块", "type": "python", "request": "launch", "module": "Project.sim.out.main", "cwd": "${fileDirname}/../../.." } ] }
方案2:调整项目结构(零配置,最易维护)
Python官方项目规范不建议将可执行入口脚本放在嵌套包内部,你可以直接把main.py移动到Project根目录下,调整后的结构如下:
Project | |- main.py |- sim | | |- out | |- libs | |- __init__.py |- plus.py
调整后main.py作为顶层入口脚本,直接使用绝对导入即可:
from libs import plus a = 1 b = 5 c = plus.sum(a,b) print(c)
此时直接在Project目录下运行python main.py即可正常执行,不需要任何额外配置,也不会出现导入错误,是日常开发中最常用的结构。
注意:Python 3.3+ 已经支持隐式命名空间包,包目录下不强制要求
__init__.py文件,但保留空的__init__.py可以避免大部分边缘场景的包识别问题,你的操作没有问题。
内容的提问来源于stack exchange,提问作者Luguecos

