使用runpy.run_path时相对导入失败的问题排查
runpy.run_path 跨目录运行脚本时的模块导入问题
目录结构
pyrun-pb ├── folder-1 │ ├── common.py │ ├── data.py │ └── test-run-1.py └── test-run-2.py
运行结果
运行test-run-1.py可正常输出:
> python /path/to/pyrun-pb/folder-1/test-run-1.py {'test': 'example'}
运行test-run-2.py则报错:
> python /path/to/pyrun-pb/test-run-2.py Traceback (most recent call last): File "/path/to/pyrun-pb/test-run-2.py", line 8, in <module> data = run_path((THIS_DIR / 'folder-1') / 'data.py') File "//path/to/python3.9/runpy.py", line 288, in run_path return _run_module_code(code, init_globals, run_name, File "//path/to/python3.9/runpy.py", line 97, in _run_module_code _run_code(code, mod_globals, init_globals, File "//path/to/python3.9/runpy.py", line 87, in _run_code exec(code, run_globals) File "/path/to/pyrun-pb/folder-1/data.py", line 3, in <module> from common import CVAR ModuleNotFoundError: No module named 'common'
代码示例
test-run-2.py
from pathlib import Path from runpy import run_path THIS_DIR = Path(__file__).parent data = run_path((THIS_DIR / 'folder-1') / 'data.py') print(data["XTRA"])
test-run-1.py
from pathlib import Path from runpy import run_path THIS_DIR = Path(__file__).parent data = run_path(THIS_DIR / 'data.py') print(data["XTRA"])
data.py
from common import CVAR XTRA = { 'test': CVAR, }
common.py
CVAR = "example"
问题原因
核心问题在于Python的模块搜索路径(sys.path)的差异:
- 运行
test-run-1.py时,脚本位于folder-1目录下,Python会自动将当前脚本所在目录(即folder-1)加入sys.path,因此data.py中from common import CVAR能找到同目录下的common.py。 - 运行
test-run-2.py时,脚本位于根目录pyrun-pb,此时sys.path默认包含根目录,但不包含folder-1。用run_path执行folder-1/data.py时,Python不会自动将folder-1加入sys.path,导致data.py无法找到common模块。
解决方法
方法1:在运行前修改sys.path
在test-run-2.py中,将folder-1目录加入模块搜索路径,再执行run_path:
from pathlib import Path from runpy import run_path import sys THIS_DIR = Path(__file__).parent folder1_path = THIS_DIR / 'folder-1' # 将folder-1添加到模块搜索路径 sys.path.append(str(folder1_path)) data = run_path(folder1_path / 'data.py') print(data["XTRA"])
方法2:改用相对导入并将folder-1设为包
- 在
folder-1目录下创建空文件__init__.py,使其成为Python包。 - 修改
data.py的导入语句为相对导入:
from .common import CVAR XTRA = { 'test': CVAR, }
- 调整
test-run-2.py的run_path调用,指定包模块名称:
from pathlib import Path from runpy import run_path THIS_DIR = Path(__file__).parent folder1_path = THIS_DIR / 'folder-1' data = run_path(folder1_path / 'data.py', run_name='folder-1.data') print(data["XTRA"])
方法3:通过环境变量添加搜索路径
运行test-run-2.py前,将folder-1目录加入PYTHONPATH环境变量:
# Linux/macOS export PYTHONPATH=/path/to/pyrun-pb/folder-1:$PYTHONPATH python /path/to/pyrun-pb/test-run-2.py # Windows set PYTHONPATH=C:\path\to\pyrun-pb\folder-1;%PYTHONPATH% python C:\path\to\pyrun-pb\test-run-2.py
内容的提问来源于stack exchange,提问作者projetmbc
相关产品推荐
相关产品推荐

