
当使用 pytest-mypy 插件时,mypy 的 exclude 配置无效,是因为 pytest 先于 mypy 发现并显式传递了被测文件——此时 mypy 会忽略 exclude 规则。解决关键在于让 pytest 根本不收集目标目录下的测试文件。
当使用 pytest-mypy 插件时,mypy 的 `exclude` 配置无效,是因为 pytest 先于 mypy 发现并显式传递了被测文件——此时 mypy 会忽略 `exclude` 规则。解决关键在于让 pytest **根本不收集**目标目录下的测试文件。
在 Python 项目中,pytest-mypy 插件会自动扫描项目内所有 .py 文件(包括非测试文件),并将它们作为 mypy 的输入源。即使你在 mypy.ini 中配置了:
[mypy] exclude = FolderNotIgnored/
该配置也不会生效——因为 pytest 已经将 FolderNotIgnored/hello.py 显式加入运行列表(如日志所示:FolderNotIgnored\hello.py ..),而 mypy 官方文档明确指出:“If a file is passed explicitly to mypy (e.g., on the command line), it will always be checked, even if it matches an exclude pattern.”
✅ 正确做法是:在 pytest 层级阻止文件被发现,而非依赖 mypy 过滤。
✅ 推荐解决方案
方案 1:命令行临时排除(适合调试)
pytest --ignore FolderNotIgnored --mypy
⚠️ 注意:
--ignore参数值为路径名(不带尾部/),且必须位于--mypy之前(顺序敏感)。
方案 2:配置文件永久排除(推荐用于项目)
在 pyproject.toml 中添加:
[tool.pytest.ini_options] norecursedirs = ["FolderNotIgnored", "__pycache__", ".git"]
或在 pytest.ini 中:
[tool:pytest] norecursedirs = FolderNotIgnored __pycache__ .git
✅
norecursedirs是 pytest 原生命令,它会在递归发现阶段跳过整个目录,确保FolderNotIgnored/下的任何.py文件都不会进入 pytest 收集队列,自然也不会传给 mypy。
❌ 错误尝试(避免)
- 在
mypy.ini中使用files = ["helloroot.py"]手动指定白名单:不可靠,易遗漏且与 pytest-mypy 插件行为冲突; - 使用
--mypy-ignore(不存在的参数)或--mypy-exclude(pytest-mypy 不支持该 flag); - 仅修改
mypy的exclude而不干预 pytest 收集流程——必然失效。
? 验证是否生效
运行后检查 pytest 输出中的 collected N items 行,确认 FolderNotIgnored/hello.py 不再出现在文件列表中(例如只显示 helloroot.py .)。同时可添加 -v 查看详细收集日志:
pytest -v --mypy
? 总结
-
mypy.exclude仅对 mypy 自动发现的文件起作用; -
pytest-mypy插件绕过了 mypy 的自动发现机制,直接将 pytest 收集到的所有.py文件显式传入; - 因此,排除逻辑必须前置到 pytest 收集阶段——使用
--ignore或norecursedirs是唯一可靠方式; - 该原则同样适用于其他可能被 pytest 错误收集的非测试代码(如示例脚本、遗留模块、生成代码等)。
遵循此模式,即可精准控制 mypy 的检查范围,避免误报和性能浪费。










