使用importlib导入带相对导入的配置文件跨路径时报ImportError如何修复
问题核心原因
- 代码中修改的
current_env是os.environ的拷贝副本,这个变量不会同步作用到当前运行的Python解释器进程,Python的模块搜索路径完全不会读取这个临时修改的副本值。 - 当脚本运行目录为
C:\Users\bar\Desktop\bar2时,Python默认的模块搜索路径不包含C:\Users\bar\Desktop,哪怕在C:\Users\bar\Desktop\a下建好了所有包结构,解释器也定位不到a这个包,自然抛出ImportError: No module named 'a'。 - 原有复制逻辑只拷贝了setting_2.py,没有把它依赖的setting_3.py放到临时目录,就算能导入成功,也会触发相对导入失败,最终拿到的
foo值是"foo2"而非预期的"foo3"。
修复步骤
- 移除无效的
current_env环境变量修改逻辑,这部分代码不会对当前进程的模块导入产生任何作用。 - 导入操作前,将临时目录的父路径显式加入当前Python进程的模块搜索路径列表
sys.path,让解释器能定位到a包。 - 将setting_2.py相对导入依赖的setting_3.py一并复制到临时目录
a下,保证相对导入逻辑能正常执行。
修正后可运行的代码
import os import sys import importlib # 原项目中依赖的配置文件实际路径 setting_2_source = r"你的原项目路径\folder_1\setting_folder\setting_2.py" setting_3_source = r"你的原项目路径\folder_1\setting_folder\setting_3.py" # 独立临时目录,与脚本运行目录无层级依赖 tmp_dir = r"C:\Users\bar\Desktop\a" os.makedirs(tmp_dir, exist_ok=True) # 自动创建不存在的临时目录 # 复制所有依赖的配置文件到临时目录 for src_file in [setting_2_source, setting_3_source]: file_name = os.path.basename(src_file) dst_file = os.path.join(tmp_dir, file_name) with open(src_file, "r", encoding="utf-8") as f: file_content = f.read() with open(dst_file, "w", encoding="utf-8") as f: f.write(file_content) # 补全临时包的__init__.py init_path = os.path.join(tmp_dir, "__init__.py") with open(init_path, "w", encoding="utf-8") as f: f.write("") # 将临时目录的父路径加入模块搜索路径 tmp_parent = os.path.dirname(tmp_dir) if tmp_parent not in sys.path: sys.path.append(tmp_parent) # 导入目标模块取值 target_mod = importlib.import_module("a.setting_2") print(target_mod.foo) # 正常输出预期值foo3
额外注意事项
- 读写文件时统一指定
utf-8编码,避免Windows环境下因为默认编码差异导致的文件读取异常。 - 不需要复制原项目中的
setting_1.py,因为直接导入a.setting_2时,只会执行临时包a下的空__init__.py,不会触发原项目setting_folder包初始化时对setting_1的导入逻辑,不会干扰最终的变量取值。 - 整个逻辑不依赖脚本运行目录的位置,只要临时目录的父路径正确加入
sys.path,无论脚本放在哪个项目下都能正常运行。
内容的提问来源于stack exchange,提问作者Giordano
相关产品推荐
相关产品推荐

