典型报错是ModuleNotFoundError: No module named 'xxx'或ImportError: attempted relative import with no known parent package,根源在于pytest未将源码目录加入sys.path,需通过python -m pytest、--pythonpath或pyproject.toml配置解决。

pytest找不到模块的典型报错是什么
看到 ModuleNotFoundError: No module named 'xxx' 或 ImportError: attempted relative import with no known parent package,基本可以确定是 Python 的模块搜索路径(sys.path)没包含你的源码目录。pytest 本身不自动把当前目录加进 sys.path,它只按 PEP 420 规则找包,且默认以“运行 pytest 的位置”为起点解析导入——不是你 cd 进去的那个目录,也不是你测试文件所在的目录。
常见诱因包括:
- 在项目根目录外执行
pytest(比如从家目录跑pytest myproject/tests/) - 项目没有
pyproject.toml或setup.py,pytest 不知道哪是源码根 - 测试文件用了相对导入(
from . import xxx),但没在包内运行 -
__init__.py缺失或位置不对,导致目录没被识别为包
怎么让pytest正确识别源码目录
最稳的方式是用 python -m pytest 替代直接调用 pytest 命令。Python 解释器会把当前工作目录加入 sys.path[0],而 pytest 作为模块运行时会继承这个路径。
实操建议:
- 确保你在项目根目录(即含
src/或myapp/子目录的地方)执行python -m pytest - 如果源码在
src/下(推荐结构),加--pythonpath src参数:python -m pytest --pythonpath src - 或者写个
pyproject.toml,明确告诉 pytest 源码在哪:[tool.pytest.ini_options] pythonpath = ["src"]
- 避免用
export PYTHONPATH=...全局设置,容易污染其他项目
为什么加 __init__.py 有时也不管用
空的 __init__.py 只能让目录变成包,但不解决“pytest 找不到这个包”的问题。关键在于:pytest 必须能从某个已知路径出发,顺着子目录找到它。比如项目结构是:myproject/
├── pyproject.toml
├── src/
│ └── myapp/
│ ├── __init__.py
│ └── core.py
└── tests/
├── __init__.py
└── test_core.py
这时 test_core.py 里写 from myapp.core import xxx,pytest 就得知道 src/ 是根。光有 __init__.py 不行,还得通过 --pythonpath 或 pythonpath 配置把它暴露出去。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
另一个坑是:IDE(如 PyCharm)可能偷偷改了 sys.path,让你在 IDE 里跑通,终端却失败——务必在纯终端里验证。
立即学习“Python免费学习笔记(深入)”;
相对导入报错怎么办
from . import xxx 或 from ..utils import yyy 这类写法,只在模块被当作包的一部分导入时才合法。直接运行测试文件(python tests/test_core.py)或 pytest 没识别到包结构时,就会崩。
解决办法只有两个:
- 删掉相对导入,全改用绝对导入(
from myapp.core import xxx),前提是路径配置已生效 - 确保测试文件本身也在包内(比如
tests/__init__.py存在),并用python -m pytest tests/启动,让 Python 把tests当作一个包来加载
python -c "import sys; print(sys.path)" 看看,比猜快得多。

















