高性能的 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:最大行宽,常见值是88或100。target-version:目标 Python 版本,例如py39、py310、py311。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:返回语句相关规则。
一个常见误区是“一开始就把所有规则打开”。更稳妥的做法是:
- 先启用基础规则,例如
E、F、I。 - 再逐步加入
B、UP、SIM等提升质量的规则。 - 对历史包袱较大的仓库,使用
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 .
这种组合的优点是:
- 规则不算过重,团队容易接受。
- 能覆盖基础错误、导入整理、现代化语法建议。
- 自动修复比例较高。
- 配置简单,适合快速接入。
对于老项目,建议采用渐进式方案:
- 先只启用
F、E、I。 - 清理一次历史问题。
- 把 Ruff 接入 pre-commit 和 CI。
- 再逐步增加
B、UP、SIM等规则。
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,建议按以下顺序推进:
- 先明确目标,是只做 lint,还是顺带统一 format。
- 从少量高价值规则开始,不要一次开满。
- 先在一个分支上批量修复历史问题。
- 接入 pre-commit,减少人工检查成本。
- 再接入 CI,作为强制门禁。
- 定期评估是否进一步替代 Black、isort 或其他工具。
这比“直接全量启用所有规则并强推到全团队”更实际,也更容易成功。
19. 总结
Ruff 是当前 Python 工程化领域非常值得采用的工具。它最大的价值不只是“快”,而是通过高性能把 lint、format、import-sort、 自动修复等能力集中起来,显著降低团队维护成本。
如果用一句话概括:
Ruff 是一个以极高性能整合 Python 代码检查、格式化和自动修复能力的现代工具,特别适合希望简化工具链并提升开发效率的团队 。
对于大多数 Python 项目,一个现实且高收益的选择是:
- 用 Ruff 负责基础 lint。
- 逐步启用自动修复。
- 视团队情况决定是否同时启用 Ruff formatter。
这样通常可以在较小迁移成本下,获得明显的工程收益。

浙公网安备 33010602011771号