Python子模块导入报错求助:跨模块调用触发ModuleNotFoundError
首先咱们拆解下问题根源:当你直接运行gannController.py时,Python会把该文件所在目录(AI/gann)以及项目根目录(如果你是从根目录执行脚本的话)加入到sys.path搜索路径中,所以from model import modelController能正常找到模块。但在convert.py中导入gannController时,Python默认只把convert目录和系统路径加入sys.path,找不到上层的model目录,因此触发报错。
下面是几种既解决导入问题,又不污染convert命名空间的可行方案:
方案1:手动添加项目根目录到sys.path(快速临时解决)
在convert.py最开头添加代码,将包含convert、AI、model的项目根目录加入Python的搜索路径,同时用别名导入避免污染命名空间:
import sys from pathlib import Path # 获取项目根目录(convert目录的父级目录) project_root = Path(__file__).parent.parent sys.path.append(str(project_root)) # 用别名导入,避免gannController直接暴露在convert的命名空间中 import AI.gann.gannController as gann_controller
这样gannController里的from model import...就能正常找到模块,你后续通过gann_controller别名访问其中内容即可。
方案2:使用相对导入(规范的包内导入方式)
如果你的项目是标准Python包(所有目录都有__init__.py),可以修改gannController.py的导入语句为相对导入,指向上层的model模块:
# gannController.py中修改导入语句 from ...model import modelController
这里的...表示向上跳两级目录(从AI/gann到AI,再到项目根目录),以此定位到model模块。之后在convert.py中依然用别名导入:
import AI.gann.gannController as gann_controller
如果需要保留直接运行gannController.py的功能,可以在文件开头加入兼容性判断:
# gannController.py开头添加 if __name__ == "__main__": import sys from pathlib import Path sys.path.append(str(Path(__file__).parent.parent.parent)) from model import modelController else: from ...model import modelController
方案3:将项目安装为可编辑包(长期维护最优方案)
如果打算长期维护这个项目,最规范的方式是把它变成可安装的Python包:
- 在项目根目录创建
pyproject.toml文件,内容示例:
[build-system] requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" [project] name = "your-project-name" version = "0.1.0" packages = ["convert", "AI", "model", "util"]
- 在项目根目录执行命令,以可编辑模式安装包:
pip install -e .
安装完成后,Python会自动将整个项目加入sys.path,你在任何地方都可以用绝对导入,且不会污染命名空间:
# convert.py中导入 import AI.gann.gannController as gann_controller # gannController.py中保持原有的绝对导入即可 from model import modelController
至于util模块的类似问题,以上方案完全适用——只要保证导入路径正确,并用别名导入避免命名空间污染即可。
内容的提问来源于stack exchange,提问作者Thijser

