Python中能否让import导入路径始终相对语句所在文件解析?
top_folder/ ├── file1.py # 顶层入口文件 └── sub_folder/ ├── file2.py └── file3.py
各文件初始代码:
top_folder/file1.py
from sub_folder.file2 import two
top_folder/sub_folder/file2.py
from file3 import three two = 2
top_folder/sub_folder/file3.py
three = 3
现象:直接运行file2无报错,运行file1时file2中的from file3 import three会抛出模块找不到错误。
报错核心原因是Python的模块搜索路径默认以入口执行脚本的所在目录为第一优先级,不会自动把被导入模块的所在目录加入搜索路径。当你从top_folder运行file1作为入口时,Python只会在top_folder目录下找file3,自然找不到sub_folder里的file3,和你推测的逻辑一致。
你现在用exec读绝对路径执行的写法属于临时hack,既没法做静态代码检查,也会重复执行模块代码,完全不符合Python项目的编码规范,有两种标准方案可以解决。
方案1:包内显式相对导入(官方推荐)
如果sub_folder是作为项目内的一个包存在,直接把file2里的导入改成相对导入即可,不需要改任何路径配置:
修改top_folder/sub_folder/file2.py的导入行:
# 原来的写法 from file3 import three 替换为下面这行 from .file3 import three
开头的.代表当前file2所在的sub_folder目录,这个路径解析是和当前文件位置绑定的,不管你从哪个位置启动入口脚本,都能准确定位到同目录下的file3。
注意:使用相对导入的文件不能直接作为入口脚本运行,如果需要单独调试file2,不要进入sub_folder目录执行
python file2.py,要回到top_folder目录执行python -m sub_folder.file2,用模块模式启动即可正常运行。
方案2:统一项目根搜索路径(兼容直接运行子文件场景)
如果你不想改启动命令,需要保留直接进入sub_folder运行file2的习惯,就在入口文件最顶部把项目根目录加入Python的系统搜索路径,保证所有导入的搜索起点一致:
修改top_folder/file1.py,在所有业务导入之前加路径配置:
import sys from pathlib import Path # 将当前file1所在的top_folder目录加入模块搜索路径 sys.path.insert(0, str(Path(__file__).parent.resolve())) from sub_folder.file2 import two
这种写法不需要修改file2的原有导入逻辑,不管是跑file1还是单独跑file2,都不会出现模块找不到的问题,可移植性也比硬编码绝对路径强很多。
- 不要用exec执行文件代码:会绕过Python的模块缓存机制,多次导入时会重复执行模块内的逻辑,也无法被IDE识别跳转,维护成本极高
- 不要硬写本地绝对路径:换设备、换部署环境直接失效,没有任何通用性
内容的提问来源于stack exchange,提问作者tonitone120

