Ruff 替换 flake8 + black + isort:一个中型 Python 仓库的迁移实录

举报
yd_213494201 发表于 2026/10/24 06:13:10 2026/10/24
【摘要】 把 flake8 + black + isort 三件套整体迁移到 Ruff 的完整记录:配置收敛到 pyproject.toml、规则分批开启、pre-commit 与 CI 落地,以及 4 个实际踩到的坑。迁移后本地 pre-commit 4.2s → 0.35s,CI lint 58s → 6s。

团队里一个 12 万行的 Python 仓库,lint 链路一直是 flake8 + black + isort 三件套串联。每次 pre-commit 要 4 秒多,CI 的 lint job 接近一分钟,而且三份配置分散在 setup.cfg、pyproject.toml 和 .isort.cfg 里,改一次规则要翻三个文件。上周我把它们整体换成了 Ruff,记录一下过程和踩过的坑,给同样在犹豫的团队一个参考。

一、为什么换

Ruff 是用 Rust 写的,一个二进制同时承担 lint 和 format,官方宣称比 flake8 快几十倍。对我们这种中型仓库来说,真正吸引人的不是跑分,而是一套配置、一条命令、一次遍历:不用再让三个工具各自 parse 一遍 AST,也不用担心 black 格式化完之后 isort 又把 import 组重排。

二、配置收敛到 pyproject.toml

装好之后,把原来的三份配置删掉,规则集中在 pyproject.toml:

[tool.ruff]
line-length = 100
target-version = "py311"
src = ["src", "tests"]

[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B", "SIM", "C4"]
ignore = ["E501"]

[tool.ruff.lint.isort]
known-first-party = ["mypkg"]

[tool.ruff.format]
quote-style = "double"

注意 known-first-party 一定要从原来的 isort 配置迁过来,否则 ruff 会把自家包当成第三方,import 分组直接乱掉,review 时一片红。

三、规则不要一次开全

我第一版直接把 select 写成 ["ALL"],结果报了两千多条。建议分三步走:先 E/F 对齐原来的 flake8,再开 I 把 import 排序接过来,最后再逐步打开 UP(pyupgrade)、B(bugbear)、SIM(简化)。每加一组之前先用 diff 看清楚影响面:

ruff check . --select I --diff | head -50

这样每一次提交都是一个可 review 的改动范围,而不是一次几千文件的格式化爆炸。

四、pre-commit 与 CI 落地

repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.6.9
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format

CI 里直接加一个 step 跑 ruff check . && ruff format --check . 即可。Ruff 是单二进制,不需要再装一圈插件包,镜像构建也快了。

五、踩过的坑

1. format 风格差异:ruff format 默认双引号、magic trailing comma 策略与 black 略有不同。先单独提交一次全量 format,不要和业务改动混在同一个 commit 里,否则 diff 无法 review。

2. noqa code 变了:原来 flake8 插件专属的 code(比如某些 plugin 的 W 系列)Ruff 没有等价实现,要么换用 Ruff 对应规则,要么临时改成裸 # noqa,别一直挂着。

3. 版本要钉死:Ruff 迭代很快,新版本可能新增规则导致流水线突然变红。pre-commit 的 rev 和 CI 的 pin 必须一致,并且统一升级节奏。

4. 编辑器双写:VS Code 装了 Ruff 扩展后,记得关掉 Python 扩展自带的 black / flake8 格式化,否则保存时两个 formatter 互相覆盖,保存一次文件抖动两次。

六、效果

本地 pre-commit 从 4.2 秒降到 0.35 秒,CI lint 阶段从 58 秒降到 6 秒左右;依赖从 black + flake8 + isort + 若干 flake8 插件共 11 个包收敛到 1 个。规则集反而更严格了——多了 bugbear 和 pyupgrade 的检查,还顺手抓到几处 except: pass 和可简化的 if/else。

结论:如果你还在维护 flake8 + black + isort 三件套,迁移成本大概是一个下午,收益是每天都在省的时间。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。