一个连一行代码都没改的 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"]。
三处工作流补丁,以及你该做什么
规则数量之外,v0.16 还补了三处开发者一直在等的缺口。
| 变化 | 具体内容 |
|---|---|
| Markdown 格式化 | ruff format 能处理 .md/.qmd 里 python/pyi/pycon 代码块,fmt: off 照常用 |
| 抑制注释升级 | 新增 ruff: ignore(行级)和 ruff: file-ignore(文件级),可带理由,--add-ignore 能自动加 |
| 诊断带 diff | check 和 format --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 没改你一行代码,只是把默认值挪了挪,选择权就悄悄换了手。
