Python跨包相对导入报错:从项目根目录通过Makefile运行训练脚本失败
问题原因
你在train.py中写入的相对路径../../src/是相对于当前执行命令的工作目录,而非train.py文件自身的存储目录:
- 当你在train.py所在目录(
src/modelling)执行时,工作目录就是src/modelling,../../src/刚好指向项目下的src目录,导包正常 - 当你在项目根目录执行时,工作目录是
<project_name>,../../src/会向上跳转两层到项目根目录的上级目录查找src,自然找不到对应模块,触发报错
快速修复方案
不需要修改项目结构,只需要把train.py中的sys.path硬编码逻辑改为基于train.py文件自身路径计算的绝对路径即可,兼容任意目录下的执行请求:
import sys from pathlib import Path # 计算train.py所在的src目录的绝对路径,不受当前工作目录影响 src_path = Path(__file__).parent.parent.resolve() sys.path.insert(0, str(src_path)) from utils.general_imports import * print("Value of X is ",X)
修改后直接在根目录执行python src/modelling/train.py或者make train都可以正常运行,同时也兼容你原来在train.py所在目录执行的使用习惯。
更优规范实现方案
如果不想在每个业务脚本里都写sys.path硬编码,同时符合你不修改PYTHONPATH环境变量的要求,可以用Python官方推荐的可编辑安装方式规范项目:
- 在项目根目录新增
pyproject.toml配置文件,内容如下:
[build-system] requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" [project] name = "替换为你的项目名" version = "0.1.0" packages = ["src"]
- 在项目根目录执行一次
pip install -e .,这个操作会把你的src目录下的包注册到Python环境中,后续修改代码不需要重新执行安装命令即可生效。 - 删除所有业务脚本中sys.path相关的硬编码代码,后续不管在哪个目录执行脚本,都可以正常导入src下的模块,
make train命令也可以直接运行。
该方案的优势是结构规范,不需要每个脚本都维护路径逻辑,后续项目需要打包、发布或者集成其他工具时也不需要额外调整配置。
注:你之前在根目录新增的空
__init__.py没有实际作用,Python 3.3+版本支持命名空间包,根目录不需要额外添加__init__.py,可以直接删除。
内容的提问来源于stack exchange,提问作者Anon
相关产品推荐
相关产品推荐

