news 2026/9/10 13:13:42

Ruff 的 --fix 没有修改代码?排查 safe 与 unsafe 修复默认策略

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ruff 的 --fix 没有修改代码?排查 safe 与 unsafe 修复默认策略

Ruff 的 --fix 没有修改代码?排查 safe 与 unsafe 修复默认策略

【免费下载链接】ruffAn extremely fast Python linter and code formatter, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/ru/ruff

运行ruff check --fix后,终端列出了一堆违规,但文件内容原封不动。多数情况下这不是 bug:Ruff 把每个自动修复标记为 safe 或 unsafe,而默认只应用 safe 修复——unsafe 修复可能会改变代码的运行时行为或删掉注释,所以必须先显式开启。这篇文章基于 Ruff 的 Linter 文档 和 FAQ,给出一条从症状到配置的完整排查路径:先判断你的修复属于哪一类、为什么没被应用,再决定是开启 unsafe 修复,还是调整 per-rule 的修复安全级别。

症状:--fix之后文件没有变化

ruff check是 Ruff linter 的主入口,--fix开启自动修复:

$ ruff check --fix # Lint current directory and fix any fixable errors.

按文档,--fix开启后 Ruff 的行为是:修复所有存在safe修复的违规;存在 unsafe 修复但未开启时,Ruff 不会应用修复,而是显示一条提示信息。所以"没修改代码"通常对应三种情况之一:

  1. 违规只有 unsafe 修复,未开启--unsafe-fixes
  2. 该规则本身不支持修复(文档要求到 rules 参考 核对每条规则的修复能力);
  3. 配置把该规则排除在修复范围之外(unfixablefixable白名单),或违规被noqa抑制而未参与修复。

先跑一次不带--fix的检查,确认违规本身存在:

$ ruff check

如果连违规都列不出来,问题在规则选择(select/ignore)而不是修复策略,需要另行处理;只有列出了违规而文件没变,才继续按下面的顺序排查。

默认策略:只有 safe 修复会被应用

Ruff 对修复安全性的定义(来自 Fix safety 章节):

  • safe:应用后代码含义不变;只有整条语句或表达式被删除时(例如删未使用的 import)才会连带移除注释;
  • unsafe:可能导致运行时行为变化、删除注释,或两者兼有。

文档给出的例子是unnecessary-iterable-allocation-for-first-elementRUF015):把list(...)[0]改写为next(iter(...))可以大幅提升性能(文档示例:前者python -m timeit测得约 1.69 sec/loop,后者约 70.8 nsec/loop,为文档示例数据而非固定预期),但集合为空时抛出的异常从IndexError变成StopIteration,可能破坏上游错误处理,因此该修复被归为 unsafe。

由此推出默认行为:Ruff 只默认启用 safe 修复。如果你的违规恰好只有 unsafe 修复,--fix单独使用时就不会写文件。

排查第一步:区分"无修复可用"与"有 unsafe 修复"

--unsafe-fixes临时把 unsafe 修复纳入,再配合--diff预览改动而不写回文件:

# 只查看 unsafe 修复会做什么(不应用) ruff check --unsafe-fixes # 预览 diff:不写回任何文件,把每个改动文件的 diff 输出到 stdout,无 diff 时退出码为 0 ruff check --fix --diff

--diff会"避免写回任何修复后的文件,改为把每个改动文件的 diff 打印到 stdout,且无 diff 时退出 0",并隐含--fix-only。用这两条命令可以快速区分:

  • 加上--unsafe-fixes后违规消失了,或--diff打出了 diff——说明违规有修复,只是属于 unsafe 且未开启;
  • 加了--unsafe-fixes--fix后违规仍在、diff 仍为空——说明该规则不支持修复,或违规被其他设置排除,继续往下排查。

另外,使用json输出格式时 Ruff 会始终展示所有修复(包括 unsafe 的),每个修复的安全级别位于applicability字段。需要脚本化判断某条违规到底有没有修复、是什么级别时,这是最直接的依据:

$ ruff check --output-format json

排查第二步:检查配置里的unfixable/fixable

Ruff 还有一层"是否允许修复"的设置,与安全级别相互独立。要限制 Ruff 修复的规则集合,用lint.fixablelint.extend-fixablelint.unfixable。两个容易踩的坑:

  • 配置里写了unfixable = ["F401"](或对应前缀),该规则的违规即使带 safe 修复也不会被--fix修改;
  • fixable是白名单语义。写成fixable = ["F401"]表示允许修复F401,其他规则的修复全部禁用——这是比unfixable更隐蔽的"没修改代码"原因。

文档给出的两个配置示例(ruff.toml写法):

# 允许所有规则修复,但排除 F401 [lint] fixable = ["ALL"] unfixable = ["F401"]
# 只允许修复 F401 [lint] fixable = ["F401"]

pyproject.toml中对应写在[tool.ruff.lint]下,键名相同。对照你自己的配置文件,确认目标规则没有被unfixable排除、也没有被fixable白名单挡在外面。

排查第三步:检查noqa抑制

ruff check默认尊重# noqa注释(可用--ignore-noqa忽略它们)。被行级# noqa: CODE或文件级# ruff: noqa抑制的违规不会出现在报告里,也不会参与修复。如果你记得代码行尾有 noqa 注释,先确认是不是这条原因。

确认是 unsafe 之后如何开启

如果你接受 unsafe 修复"可能不保留代码原意"(这是 args 定义 中--unsafe-fixes的原文描述),有两条开启路径:

# 查看 unsafe 修复 ruff check --unsafe-fixes # 应用 unsafe 修复 ruff check --fix --unsafe-fixes

或者在配置文件中设置unsafe-fixesruff.toml顶层键;pyproject.toml[tool.ruff]下同名键),避免每次都带命令行参数:

# ruff.toml unsafe-fixes = true

反向的提示抑制也值得知道:默认情况下,当存在可用但未开启的 unsafe 修复时,Ruff 会显示一条提示;把unsafe-fixes设为false或传--no-unsafe-fixes可以关掉这条提示。

可选:按规则调整修复安全级别

如果你只对个别规则信任 unsafe 修复(或反过来,觉得某个 safe 修复在你的场景下不安全),不必全局开关,可以用lint.extend-safe-fixeslint.extend-unsafe-fixes逐规则升降级。文档示例:把F601的 unsafe 修复提升为 safe,同时把UP034的 safe 修复降级为 unsafe:

# ruff.toml [lint] extend-safe-fixes = ["F601"] extend-unsafe-fixes = ["UP034"]
# pyproject.toml [tool.ruff.lint] extend-safe-fixes = ["F601"] extend-unsafe-fixes = ["UP034"]

这两个设置同样接受前缀,比如F表示把 Pyflakes 全部规则的修复提升为 safe。注意它们是extend语义:在默认安全级别基础上做增量调整,适合"全局保持默认、个别规则例外"的场景。

验证修复是否生效

确认修复路径选对之后,用下面几种方式验证结果:

$ ruff check --fix --show-fixes

--show-fixes会在修复后列出所有被修复的违规,方便逐条核对。退出码是最客观的判定(Exit codes 章节):

  • 0:没有违规,或所有违规都被自动修复了;
  • 1:仍有违规;
  • 2:配置、CLI 选项或内部错误导致异常终止。

也就是说,ruff check --fix跑完退出码为0,说明违规已清零(包括被修复的部分);退出码为1时,剩余违规要么没有可用修复,要么属于未开启的 unsafe 修复,可以再用--diff预览它们会如何被修改。

限制与已知边界

  • 判断某条规则是否可修复,文档给出的依据是 rules 参考 中每条规则的修复标注,没有更快的全局开关可查。
  • FAQ 明确承认:由于 Python 的动态性,即使是看似 trivial 的 safe 修复也无法保证 100% 不出问题。如果 safe 修复改坏了你的代码,文档建议提交 Issue,而不是自行归类为"unsafe 未开启"。
  • unsafe 修复的开启是项目级决策:--unsafe-fixes只影响当次命令,unsafe-fixes = true则对所有使用者生效,两者语义一致(包含可能不保留原意的修复),按团队能接受的程度选择写在 CLI 还是配置文件里。

按这条路径走完,--fix没动文件的原因就落在三处之一:unsafe 修复未开启(加--fix --unsafe-fixes或配置unsafe-fixes = true)、规则/配置层面被fixable/unfixablenoqa排除(调整对应配置),或者该规则本身不支持修复(无解,只能手动修改)。

【免费下载链接】ruffAn extremely fast Python linter and code formatter, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/ru/ruff

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 13:12:43

STM32三闭环PID控制:位置-速度-电流实时实现指南

简介:本资源是一套基于STM32F4平台实现直流有刷电机位置-速度-电流三闭环PID控制的完整嵌入式工程,面向自动化、机器人及运动控制方向的嵌入式开发者与高校高年级学生,解决电机多层级动态响应精度低、参数整定难、软硬件协同调试复杂等实际问…

作者头像 李华
网站建设 2026/9/10 13:10:46

基于LSTM的锂电池剩余寿命预测Matlab实现与调优

简介:面向锂电池健康管理、电池管理系统相关研究人员与工程师,提供一套基于长短期记忆(LSTM)神经网络的锂电池剩余寿命预测Matlab完整实现。资源直击剩余使用寿命(RUL)预测中数据准备与网络搭建两大难点&am…

作者头像 李华