2025-10-06,我记录过一个很别扭的排错场景:mypy 和 ruff 已经修到 0 错误,VS Code 里仍然有报错。当时我怀疑三处配置冲突:pyrightconfig.json 放在 backend 目录、exclude 却用了相对路径;根目录的 settings.json 可能没有被 Pylance 正确读取;setup.cfg 和 mypy.ini 又有重复配置。
这些是当时的观察,不是已经确认的根因。本轮也没有回到那个工程复现。不过有一点需要先纠正:VS Code 不会读取任意位置的 settings.json,单文件夹工作区设置通常放在 .vscode/settings.json;多根工作区的工作区级设置可放在 .code-workspace 文件,用户设置则在用户配置目录。根目录下单独一个 settings.json,本身就不是 VS Code 的工作区设置文件。下面把这四层拆开,目的是让“命令行通过、IDE 报错”变成可以逐项核对的差异,而不是靠反复重启碰运气。
第一层:两个工具检查的不是同一件事
mypy、ruff 和 Pylance/Pyright 是不同的工具。mypy 与 Pyright 做类型检查;ruff 提供 lint 和格式化,下面的 ruff check 命令只检查 lint。它们的规则实现、默认严格度和配置项并不相同。一个工具 0 错误,只说明它按自己的规则、自己的配置跑完没有报错。
先分别在命令行复现:
python -m mypy backend
python -m ruff check backend
pyright
记录每个命令的版本:
python -m mypy --version
python -m ruff --version
pyright --version
IDE 内置的 Pyright 版本可能和命令行安装的版本不同,规则集和默认行为也就可能不同,这一步不能跳过。
第二层:IDE 用的是哪个解释器
VS Code 的 Python 扩展会在状态栏显示当前解释器。点开选择器,确认路径是否指向项目的 .venv,而不是系统 Python 或另一个环境。可以在命令面板执行 Python: Select Interpreter,也可以在终端里对照:
python -c "import sys; print(sys.executable)"
如果 IDE 的解释器指向另一个环境,第三方库的导入解析可能不同。先对齐解释器,再单独检查 python.analysis.extraPaths 的路径是否指向预期位置。
第三层:配置文件放在哪里,谁在读
Pyright 配置文档(https://github.com/microsoft/pyright/blob/main/docs/configuration.md)说明:默认配置文件位于项目根目录;同时存在 pyrightconfig.json 和含 Pyright 设置的 pyproject.toml 时,前者优先。文档也支持多根工作区,每个工作区根可以有自己的配置。
如果文件放在 backend/,而编辑器把仓库根目录当作项目根,配置就可能没有被当作预期的那一份读取。此时不是“配置写错了”,而是“读的不是这一份”。
路径解析也要按配置文件所在的项目根来写。假设仓库结构是:
repo/
backend/
app/
.venv/
pyrightconfig.json
如果 Pyright 把 backend 当作项目根,配置应写成:
{
"include": ["app"],
"exclude": [".venv", "**/migrations"]
}
如果仍按仓库根写 backend/.venv,排除规则就可能落空。单根项目可以让 IDE 打开的目录与配置文件所在根一致;多根工作区应逐个核对根目录与配置,命令行也可用 pyright --project 明确指定配置位置。
第四层:规则来源是否重复
同一类检查散落在 setup.cfg、mypy.ini、pyproject.toml、ruff.toml 和编辑器设置里时,很难判断哪一条真正生效。先列出所有配置文件,再按工具归并:
find . -maxdepth 3 \( -name "pyproject.toml" -o -name "setup.cfg" -o -name "mypy.ini" -o -name "ruff.toml" -o -name "pyrightconfig.json" \)
Windows 没有 find 时,可以直接在资源管理器搜索这几个文件名,或使用 Git Bash 执行上面的命令。
这里说的编辑器设置,指 VS Code 的用户设置或工作区 .vscode/settings.json。在命令面板执行 Preferences: Open Workspace Settings (JSON),打开的那份是当前工作区设置之一,多根工作区还要核对各文件夹设置;如果配置写在仓库根目录的 settings.json 里,它不会因为文件名相同就被读取。
归并原则不是“文件越少越好”,而是每类规则只有一个可核对的来源。比如 mypy 配置放在 pyproject.toml,ruff 也放在同一文件的不同表里,Pyright 用 pyrightconfig.json,编辑器只保留解释器和少量 UI 设置。这样出问题时能直接指到一段配置。
VS Code Python 设置参考(https://code.visualstudio.com/docs/python/settings-reference)中的两个设置需要区别对待:
- python.analysis.extraPaths:官方说明是 Specifies extra search paths for import resolution.,用于补充导入搜索路径;
- python.analysis.diagnosticSeverityOverrides:官方说明是 Allows a user to override the severity levels for individual diagnostics.,用于调整单条诊断的严重级别。
前者补充导入搜索路径,可帮助排查部分模块解析问题;后者调整诊断严重级别,并不修复错误。把后者当成万能消音器,会把真实类型错误一起藏掉。
一张定位顺序表
| 现象 | 先查 | 不要先做 |
|---|---|---|
| 命令行 0 错误,IDE 报导入失败 | IDE 解释器、extraPaths、项目根 | 直接加 # type: ignore |
| 同一文件两边报不同错误 | 两边工具版本、规则配置来源 | 断言 IDE 一定误报 |
| 排除目录在 IDE 不生效 | 配置文件位置、相对路径基准 | 反复重装扩展 |
| 某条规则一边有一边没有 | diagnosticSeverityOverrides、规则表 | 全局关闭该规则 |
收敛配置的可执行顺序
- 单根项目固定项目根;多根工作区逐个核对各自的 pyrightconfig.json。
- 在 IDE 选择项目 .venv 的解释器,命令行用同一路径执行 python -m mypy 和 python -m ruff。
- 把 mypy、ruff 的配置各归并到一个来源,删掉重复段之前先备份并记录差异。
- 只在确有必要时使用 extraPaths 和严重级别覆盖,并在提交说明里写原因。
- 把四个版本号写进排错记录:Python、mypy、ruff、Pyright。
“界面全绿”不是目标。更实际的目标是知道每个工具读取了哪份配置、使用了哪个环境,并能解释诊断为何不同。不同检查器的规则并不相同,即使环境一致,也不保证诊断完全一致。
本文由 AI 助手依据本人历史素材起草;2025-10-06 的配置冲突是当时观察,本轮未复现或确认根因;Pyright 与 VS Code 官方文档引用已在文中标注,配置片段为说明用示例。