pytest导入报错ModuleNotFoundError,如何正确导入模块?
解决方案:Python项目测试与主程序导入冲突问题
问题背景
项目目录结构:
app/ pyproject.toml src/ app/ __init__.py app.py functions1.py functions2.py tests/ test_functions1.py test_functions2.py
- 主程序运行命令:
app>python path/to/app/src/app/app.py -flags,可正常执行 - pytest测试命令:
app>pytest path/to/app/tests/test_functions1.py,报错:
ImportError while importing test module 'path/to/app/tests/test_functions1.py'. Hint: make sure your test modules/packages have valid Python names. Traceback: tests\test_functions1.py:9: in <module> from app.functions1 import MyClass src\app\functions1.py:13: in <module> from functions2 import other_function E ModuleNotFoundError: No module named 'functions2'
已配置pyproject.toml:
[tool.pytest.ini_options] pythonpath = "src" addopts = [ "--import-mode=importlib", ]
修改functions1.py导入为from app.functions2 import other_function后测试正常,但主程序运行报错ModuleNotFoundError: No module named 'app'。
核心原因
两种运行场景的Python环境sys.path不同:
- 直接运行
app.py时,sys.path包含src/app/目录,所以同目录的functions2.py可直接通过from functions2 import ...导入 - 运行pytest时,
sys.path被配置为包含src/目录,此时Python会从src/下查找包,functions2.py属于app包,必须通过from app.functions2 import ...导入
三种可行解决方法
方法1:统一绝对导入,用模块方式启动主程序
- 将
functions1.py中的导入语句改为绝对导入:from app.functions2 import other_function - 主程序不再直接运行
app.py,改用模块方式启动(在app/目录下执行):
(因为python -m app.app -flagspyproject.toml已配置pythonpath = "src",Python会自动从src/下识别app包)
方法2:使用相对导入
在functions1.py中用相对导入引用同包内的模块:
from .functions2 import other_function
- 该方式仅适用于包内部模块间的引用,同时主程序建议仍用模块方式启动(
python -m app.app -flags),避免直接运行app.py时出现相对导入报错。
方法3:临时调整主程序的sys.path(不推荐)
如果必须直接运行app.py,可在app.py开头添加代码,手动将src/目录加入sys.path:
import sys from pathlib import Path # 将src目录添加到系统路径 sys.path.append(str(Path(__file__).parent.parent))
- 此方法能临时解决路径问题,但不够优雅,易引发其他路径相关的潜在问题,仅作应急方案。
内容的提问来源于stack exchange,提问作者Tim Kirkwood
相关产品推荐
相关产品推荐

