pytest --mypy 默认以 Python 3.8 模式运行,导致 int | str、match 类型缩小、list[str] 等 3.10+ 语法不被识别;需在项目根目录配置 mypy.ini,明确指定 python_version = 3.10(无引号)和 strict = True,并安装对应 types-stubs 包。

因为 pytest --mypy 默认用 Python 3.8 兼容模式运行,根本不会解析 int | str、list[str] 或 match 分支里的类型推导——不是你写错了,是 mypy 压根没按 3.10+ 规则干活。
pytest --mypy 为什么默认不认 Python 3.10+ 语法
插件本身不设 Python 版本,全靠底层 mypy 决定。而 mypy 若未显式指定 python_version,就会 fallback 到 3.8 模式:
-
int | str被当成语法错误,而非合法联合类型 -
match表达式中变量的类型无法被正确缩小(比如匹配str后仍报Any) -
list[str]这类泛型简写被忽略,或与List[str]混淆报错 -
mypy.ini文件即使存在,也可能因运行路径不对被跳过
必须显式配置 python_version 和 strict
在项目根目录放 mypy.ini,内容至少包含:
[mypy] python_version = 3.10 strict = True disallow_untyped_defs = True check_untyped_defs = True
注意三点:
立即学习“Python免费学习笔记(深入)”;
-
python_version = 3.10不能加引号,"3.10"会被 mypy 静默忽略 - 如果你实际用的是 3.11 或 3.12,这里必须严格一致,否则
Literal、Self等新类型无法识别 -
strict = True是快捷开关,会自动启用二十多项检查;若只想开部分,就别用它,逐项写明
第三方库类型缺失不是警告,是硬伤
mypy 默认对 requests.get()、datetime.now() 这类调用只看到 Any,根本不会报错——这不是“检查宽松”,是类型信息压根不存在。
必须安装对应 stub 包:
pip install types-requests types-python-dateutil types-pytz types-Pillow- 包名必须和原库完全一致:
types-Flask✅,types-flask❌ - 有些库(如
numpy>=1.21、django>=4.1)已自带类型,装types-numpy反而可能冲突
只跑类型检查,不执行测试函数
开发中常要快速验证类型改动,又不想等所有单元测试跑完。直接运行:
pytest --mypy --mypy-ignore-missing-imports
就能跳过 import 错误(比如还没装 stub 包时),专注看类型逻辑。但注意:--mypy-ignore-missing-imports 是临时手段,上线前必须补全 stub 包,否则外部调用的类型安全就是空谈。
真正容易被忽略的,是 mypy.ini 的加载路径和 python_version 的字符串格式——这两处出错,整个类型检查就静默失效,连 warning 都不会给你。


















