高性能的 Python 代码格式化工具 Ruff

高性能的 Python 代码格式化工具 Ruff

Ruff 工具详解

1. Ruff 是什么

Ruff 是一个面向 Python 生态的高性能代码质量工具,由 Rust 编写。它的核心目标是用极快的速度提供 Python 静态检查、代码格式 化以及部分自动修复能力,从而替代或整合多个传统工具的职责。

简单理解,Ruff 可以看作以下几类工具能力的集合:

  • Linter:检查代码风格、潜在错误、坏味道和部分安全问题。
  • Formatter:统一代码格式,作用类似 Black。
  • Import sorter:整理导入顺序,作用类似 isort 的常见场景。
  • Fixer:自动修复一部分可安全处理的问题。

Ruff 在实际项目里最突出的特点不是“功能新奇”,而是“够快、够统一、够省事”。对于大型仓库、CI 流水线、编辑器实时反馈场景,它的优势尤其明显。


2. Ruff 解决了什么问题

在 Ruff 出现之前,一个典型 Python 项目往往会同时使用多种工具:

  • Flake8:基础风格和错误检查。
  • pycodestyle:PEP 8 风格检查。
  • pyflakes:未使用变量、未定义名称等问题检查。
  • isort:导入排序。
  • Black:代码格式化。
  • pylint:更严格、更重的静态检查。
  • 各种 Flake8 插件:补充复杂度、安全、命名、简化写法等规则。

这会带来几个常见问题:

  • 工具链较多,安装和维护成本高。
  • 配置分散,团队难以统一标准。
  • 执行速度慢,影响本地开发体验和 CI 时长。
  • 工具之间可能规则重叠,甚至互相冲突。

Ruff 的价值就在于:

  • 把大量常见规则整合到一个工具中。
  • 以极高性能运行检查和修复。
  • 尽量兼容 Black 等主流工具的行为。
  • 减少团队的工具数量和维护复杂度。

3. Ruff 的核心能力

3.1 代码检查(Lint)

Ruff 最核心的能力是 lint。它可以发现:

  • 未使用的导入。
  • 未使用的变量。
  • 未定义的名称。
  • 重复定义。
  • 不符合风格规范的写法。
  • 可以简化的语法结构。
  • 一些潜在 bug。
  • 一些常见的性能和可维护性问题。

Ruff 支持非常多的规则族,很多都来自历史上常用的 Flake8 插件生态。

3.2 自动修复(Auto-fix)

对一部分规则,Ruff 可以直接自动修复。例如:

  • 删除未使用的导入。
  • 调整导入顺序。
  • 替换部分可简化写法。
  • 统一某些风格问题。

这能显著减少人工整理代码的时间。

3.3 代码格式化(Format)

Ruff 提供独立的 formatter,可用于统一代码风格。它的设计目标之一是与 Black 高度兼容,因此团队从 Black 迁移到 Ruff formatter 的成本通常较低。

3.4 导入整理

Ruff 可以处理常见的 import 排序和分组问题。对于很多项目来说,这意味着不再需要单独保留 isort。


4. Ruff 为什么流行

Ruff 近几年快速流行,主要有以下原因:

  • 速度快:Rust 实现,性能远高于很多传统 Python 工具组合。
  • 工具整合度高:减少多工具并存带来的配置复杂度。
  • 上手简单:默认行为比较合理,适合快速落地。
  • 生态兼容性好:能兼容大量现有规范和工作流。
  • 适合 CI:执行时间短,特别适合提交前检查和持续集成。
  • 编辑器体验好:实时反馈更顺畅,不容易卡顿。

对于大型代码库,Ruff 的性能优势往往不是“小优化”,而是能直接改变团队是否愿意持续运行静态检查。


5. 安装方式

常见安装方式如下。

5.1 使用 pip 安装

pip install ruff

5.2 使用 uv 安装

uv tool install ruff

或者作为项目依赖:

uv add --dev ruff

5.3 使用 Poetry 安装

poetry add --group dev ruff

通常建议把 Ruff 作为开发依赖加入项目,而不是只依赖全局安装,这样团队和 CI 的版本更一致。


6. 常用命令

6.1 检查代码

ruff check .

这会扫描当前目录下的 Python 代码并输出问题。

6.2 自动修复可修复问题

ruff check . --fix

如果只想查看问题而不修改代码,不要加 --fix

6.3 仅格式化代码

ruff format .

这相当于用 Ruff formatter 对代码进行统一格式化。

6.4 检查格式是否符合要求

ruff format . --check

这个命令适合放在 CI 中,用来判断是否存在未格式化文件。

6.5 查看将要修复的内容

ruff check . --fix --diff

它会显示差异而不直接落盘,适合先确认修改影响。

6.6 针对单文件检查

ruff check src/app.py

6.7 查看版本

ruff --version

7. 配置文件写法

Ruff 推荐配置写在 pyproject.toml 中,也支持独立的 ruff.toml.ruff.toml

最常见的是在 pyproject.toml 里配置:

[tool.ruff]
line-length = 88
target-version = "py311"

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

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

7.1 关键配置项说明

  • line-length:最大行宽,常见值是 88100
  • target-version:目标 Python 版本,例如 py39py310py311
  • select:启用哪些规则族。
  • ignore:忽略哪些规则。
  • exclude:排除目录或文件。
  • fix:是否默认启用修复,通常仍建议在命令行显式传入。

7.2 更完整的示例

[tool.ruff]
line-length = 100
target-version = "py311"
exclude = [
  ".git",
  ".venv",
  "build",
  "dist",
  "migrations",
]

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

[tool.ruff.lint.per-file-ignores]
"tests/*" = ["S101"]
"__init__.py" = ["F401"]

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"
docstring-code-format = true

这里的含义是:

  • 项目目标版本为 Python 3.11。
  • 默认启用多个规则族。
  • 忽略 E501,即行长超限问题。
  • 对测试目录和 __init__.py 单独放宽部分规则。
  • 启用文档字符串中的代码块格式化。

8. 常见规则族说明

Ruff 的规则很多,实际使用时不需要一次全部启用。常见规则族如下:

  • E / W:来自 pycodestyle 的错误和警告。
  • F:来自 Pyflakes,主要关注潜在错误。
  • I:import 排序相关。
  • B:来自 bugbear,关注潜在 bug 和坏味道。
  • UP:来自 pyupgrade,提示可升级为更现代 Python 写法。
  • SIM:来自 flake8-simplify,建议更简洁表达。
  • C4:来自 flake8-comprehensions,优化推导式写法。
  • ARG:函数参数未使用等问题。
  • N:命名规范检查。
  • S:安全相关规则,部分来自 bandit 风格检查。
  • PT:pytest 风格规则。
  • RET:返回语句相关规则。

一个常见误区是“一开始就把所有规则打开”。更稳妥的做法是:

  • 先启用基础规则,例如 EFI
  • 再逐步加入 BUPSIM 等提升质量的规则。
  • 对历史包袱较大的仓库,使用 per-file-ignores 分阶段治理。

9. Ruff 与 Black、Flake8、isort 的关系

9.1 Ruff 与 Flake8

Ruff 在很多场景下可以替代 Flake8 以及大量 Flake8 插件。它们都做代码检查,但 Ruff 通常:

  • 更快。
  • 规则覆盖更集中。
  • 自动修复能力更强。
  • 配置体验更统一。

如果你的项目现在使用的是 flake8 + 多个插件,迁移到 Ruff 往往能显著简化依赖。

9.2 Ruff 与 isort

Ruff 可以处理 import 排序,因此在多数常规项目里,可以直接替代 isort。

9.3 Ruff 与 Black

Ruff formatter 的目标之一是和 Black 保持高度兼容。二者关系通常有三种用法:

  • 只用 Ruff lint,格式化继续用 Black。
  • 同时用 Ruff lint + Ruff format
  • 用 Ruff 替代 Black 和 isort,形成单工具方案。

如果你的团队已经深度依赖 Black,先保留 Black 也完全合理;如果希望进一步减少工具数量,则可以评估迁移到 ruff format


10. 推荐的落地方式

对于新项目,比较稳妥的做法是:

[tool.ruff]
line-length = 88
target-version = "py311"

[tool.ruff.lint]
select = ["E", "F", "I", "B", "UP"]

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

配合以下命令:

ruff check . --fix
ruff format .

这种组合的优点是:

  • 规则不算过重,团队容易接受。
  • 能覆盖基础错误、导入整理、现代化语法建议。
  • 自动修复比例较高。
  • 配置简单,适合快速接入。

对于老项目,建议采用渐进式方案:

  1. 先只启用 FEI
  2. 清理一次历史问题。
  3. 把 Ruff 接入 pre-commit 和 CI。
  4. 再逐步增加 BUPSIM 等规则。

11. 与 pre-commit 集成

Ruff 很适合放在 pre-commit 中,在提交前自动检查和修复。

示例:

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

这样做的好处是:

  • 提交前就能拦截明显问题。
  • 自动修复常见格式和 import 问题。
  • 减少 CI 失败次数。

12. 与 CI 集成

在 CI 中,通常不建议直接修改代码,而是做“检查模式”。

常见命令:

ruff check .
ruff format . --check

如果想保证 import、风格、格式完全一致,这两条通常已经足够覆盖大部分团队需求。


13. 编辑器集成

Ruff 可集成到常见编辑器,例如:

  • VS Code
  • PyCharm
  • Neovim
  • Emacs

集成后通常可以获得:

  • 保存时自动格式化。
  • 实时 lint 提示。
  • 快速修复部分问题。

对开发者体验来说,这一点很重要。静态检查如果反馈太慢,团队往往会逐渐忽略它;而 Ruff 的速度使它更适合做“持续、即时”的反馈工具。


14. Ruff 的优点

Ruff 的主要优点包括:

  • 性能非常高:适合大仓库和高频执行。
  • 可替代多个工具:降低依赖和维护成本。
  • 自动修复能力强:减少机械性修改。
  • 配置集中:通常在 pyproject.toml 中统一管理。
  • 适合团队协作:规则统一,结果稳定。
  • 更容易接入 CI/CD:执行快,失败信息清晰。

15. Ruff 的局限与注意事项

Ruff 很强,但并不意味着它在所有维度都完全替代所有工具。

需要注意的点包括:

  • 不是所有规则都该一次性启用:规则太多会带来大量历史噪音。
  • 自动修复并非全能:有些问题仍需要人工判断。
  • 与现有工具存在迁移成本:尤其是老项目已有复杂 Flake8/Pylint 规则时。
  • Pylint 某些深度语义检查仍可能更细:Ruff 更偏向高性能、实用主义的代码质量治理。
  • 格式化兼容虽高,但仍应先在小范围验证:特别是团队已经深度依赖 Black 输出细节时。

也就是说,Ruff 非常适合作为“主力工程化工具”,但是否需要完全替代其他工具,仍应根据团队实际情况决定。


16. 适合什么项目

Ruff 几乎适合所有 Python 项目,尤其适合以下场景:

  • 希望统一 lint、format、import-sort 的团队。
  • CI 时间敏感的大型仓库。
  • 需要快速本地反馈的日常开发环境。
  • 想从 Flake8 + isort + Black + 若干插件 简化为更少工具的项目。
  • 新项目,希望一开始就建立统一代码规范。

如果你的项目极度依赖 Pylint 的深度规则体系,也可以采用混合方案:

  • 以 Ruff 负责高频基础检查和格式化。
  • 保留 Pylint 处理少数更重的专项规则。

17. 一个实用示例

假设你有一个 Python 项目,希望建立一套简单而高效的规范,可以这样做。

17.1 pyproject.toml

[tool.ruff]
line-length = 88
target-version = "py311"

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

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
docstring-code-format = true

17.2 本地执行

ruff check . --fix
ruff format .

17.3 CI 执行

ruff check .
ruff format . --check

这套方案的特点是:

  • 本地允许自动修复,提高开发效率。
  • CI 只做校验,保证仓库一致性。
  • 规则适中,不会让团队一上来承受过多治理成本。

18. 学习和使用建议

如果你准备在团队里推广 Ruff,建议按以下顺序推进:

  1. 先明确目标,是只做 lint,还是顺带统一 format。
  2. 从少量高价值规则开始,不要一次开满。
  3. 先在一个分支上批量修复历史问题。
  4. 接入 pre-commit,减少人工检查成本。
  5. 再接入 CI,作为强制门禁。
  6. 定期评估是否进一步替代 Black、isort 或其他工具。

这比“直接全量启用所有规则并强推到全团队”更实际,也更容易成功。


19. 总结

Ruff 是当前 Python 工程化领域非常值得采用的工具。它最大的价值不只是“快”,而是通过高性能把 lint、format、import-sort、 自动修复等能力集中起来,显著降低团队维护成本。

如果用一句话概括:

Ruff 是一个以极高性能整合 Python 代码检查、格式化和自动修复能力的现代工具,特别适合希望简化工具链并提升开发效率的团队 。

对于大多数 Python 项目,一个现实且高收益的选择是:

  • 用 Ruff 负责基础 lint。
  • 逐步启用自动修复。
  • 视团队情况决定是否同时启用 Ruff formatter。

这样通常可以在较小迁移成本下,获得明显的工程收益。

posted @ 2026-06-11 14:42  michaelchengjl  阅读(9)  评论(0)    收藏  举报