一个连一行代码都没改的 Python 项目,跑一次 ruff 升级到 v0.16.0,可能凭空多出几十条新诊断。不是代码变差了,是 Ruff 把默认启用规则从 59 条一次性拉到了 413 条

这批新规则大多老早就写好了,只是过去一直没被默认打开——这一版才把开关拨到"开"。被默认打开的这批里,恰好包含能揪出语法错误和运行时错误的规则,以前不默认开,出问题 Ruff 也不拦。默认值一变,项目"合格"的门槛也跟着变了。

速读:谁会被 413 条规则绊一下

同期,Ruff 规则库总量也从 708 条涨到 968 条,新增默认规则来自 flake8-bugbear、pyupgrade 和 Ruff 自家的 RUF 类别。谁会被这次调整绊一下,主要看项目怎么配置规则,不能一概而论。

配置方式是否受影响
select = [...] 完全自定义规则集合不受影响,规则集合仍由你指定
extend-select 在默认基础上加规则受影响,新默认规则会叠加进来
没配过规则,直接吃默认受影响最大,可能一次性冒出大量新诊断

想退回旧行为,一行配置就够:select = ["E4", "E7", "E9", "F"]

默认规则扩容有多猛 默认启用规则 59 413 规则库总量 708 968 增量多是早就存在、此前未默认开启的规则

三处工作流补丁,以及你该做什么

规则数量之外,v0.16 还补了三处开发者一直在等的缺口。

变化具体内容
Markdown 格式化ruff format 能处理 .md/.qmd 里 python/pyi/pycon 代码块,fmt: off 照常用
抑制注释升级新增 ruff: ignore(行级)和 ruff: file-ignore(文件级),可带理由,--add-ignore 能自动加
诊断带 diffcheckformat --check 直接输出修复前后对比,不用再单跑 --diff

JSON 输出的兼容性也变了。filename、location 等字段现在可能是 null,不再默认给空字符串或第 1 行第 1 列。接了机器解析或 CI 集成的团队,升级前最好跑一次全量输出核对一遍。

升级前具体该做什么,取决于你是哪类团队:

团队情况建议动作
select 自定义规则集合基本无需动作
extend-select 或吃默认配置先跑 ruff check --statistics 摸底新增诊断量,再决定分批修复还是暂缓
lint 结果接入 CI 门禁先在非阻断模式跑一遍,确认不会突然卡住合并
依赖 JSON 输出做机器解析检查 null 字段兼容性,避免解析崩溃

锐评:规则涨价,拿主意的权力在挪位

这套打法像极了 Prettier 当年在 JS 生态干的事:不给太多选项,直接给一份"合理默认",谁用谁被拉进它定的规范。区别是 Prettier 只管格式,Ruff 现在连"什么该报错"都开始替你拿主意。

好处是真的。大量项目根本不知道这些规则存在,现在不用配置就能被提醒语法错误和运行时隐患,这是实打实的开箱即用体验。

但代价也写在同一份 changelog 里。默认权重从"你选"变成了"它选",而且 968 条规则里还有 555 条没进默认集合——下一次哪些规则会被转正、转正的判断标准是什么,官方目前没细说,这是接下来最该盯的变量。

原文也没给出误报率或采纳成本的数据,规则变多不能直接等同于代码质量变好,更不代表噪音一定会增加。真正吃亏的,是那些一直靠默认配置过日子、又没读过这份配置具体写了什么的团队。

孙子讲"不战而屈人之兵"——Ruff 没改你一行代码,只是把默认值挪了挪,选择权就悄悄换了手。