TL;DR: Ruff 格式化工具是一款用 Rust 编写的超快 Python 格式化工具。它比 Black 快 30 倍以上,比 YAPF 快 100 倍,能在几毫秒内格式化大型 Python 项目 — 同时实现超过 99.9% 的 Black 兼容性。


一年多前,我提交了 Ruff 的第一次提交,它是一款用 Rust 编写的超快 Python 代码检查工具。从那时起,Ruff 每周下载量已达数百万,支持数百条检查规则,可替代数十种工具,例如 Flake8isortpyupgrade

今天标志着我们自代码检查工具发布以来最大的版本更新:Ruff 的 Python 格式化工具,现在可通过 pip install ruffruff format 进行 Beta 版体验。

0s 5s 10s 15s 20s ruff black yapf autopep8 3.20s 17.77s 19.56s 0.10s

正在格式化 Zulip 代码库(约 250,000 行代码),不使用缓存。

格式化工具的设计和实现遵循了与代码检查工具相同的指导原则

  1. 对性能的极致追求。 Ruff 的格式化工具比 Black 快 30 倍以上,比 YAPF 快 100 倍,能在几毫秒内格式化大型 Python 项目。即使禁用缓存,Ruff 的格式化工具也比 Black 启用缓存时更快。它真的非常快!
  2. 为采纳而优化。 Ruff 的格式化工具被设计为 Black 的直接替代品。在经过 Black 格式化的 Python 项目中,Ruff 在更改行数方面实现了与 Black 超过 99.9% 的兼容性。例如,在格式化 Django 代码库时,Ruff 和 Black 在 2,772 个文件中仅有 34 个文件存在差异。专注于兼容性使得项目能够以最小的干扰采纳 Ruff 格式化工具。
  3. 可配置,且具有熟悉的默认值。 Ruff 的格式化工具旨在开箱即用地兼容 Black — 这意味着它具有出色的默认值,无需任何配置。但它也公开了一些额外的设置。例如,用户可以配置所需的引号(单引号或双引号)和缩进样式。
  4. 简化的工具链。 ruff format 内置于 Ruff 中,而非作为独立软件包发布,这让您可以简化项目的依赖项并少学习一个命令行界面。我们的目标是为 Python 构建一个类似 Cargo 的体验:一个流线型的工作流程,使您的工具“开箱即用”并组合成一个统一的工具链

除了您期望的核心功能,Ruff 的格式化工具还包括

  • 支持解析和格式化 Python 3.12 代码。
  • 内置支持格式化 Jupyter notebooks。
  • 通过我们的 VS Code 扩展语言服务器 实现编辑器集成,以及社区维护的扩展(如 Ruff IntelliJ 插件),可对数千行文件实现即时保存格式化。

立即使用 pip install ruffruff format 尝试一下。

为什么要构建格式化工具?

在 Python 社区中,Black 是代码格式化的绝大多数流行选择。我一直是 Black 的用户和粉丝 — 它是一个很棒的工具!那么,为什么要构建一个格式化工具呢?

对于 Ruff 格式化工具,我们的目标不是在代码风格上创新,而是要在性能上创新,并在 Ruff 的代码检查工具、格式化工具和未来工具之间提供统一的体验

我们相信统一的工具链将带来一套更优秀、复杂度更低的工具。随着我们改进解析器和其他核心基础设施,代码检查工具和格式化工具都将受益。随着我们深化代码检查工具和格式化工具之间的集成,这两个工具都将变得更强大 — 例如,将来我们会自动格式化代码检查工具的代码修复,并对无效的 # fmt: on# fmt: off 注释提出检查违规。

以统一的工具链为我们的北极星,我们为格式化工具设定了两个主要目标

1. 超快

对于格式化工具,我们的目标是实现数量级的性能提升。当一个工具快 10 倍、20 倍或 100 倍时,它会彻底改变用户体验。以前需要“只对已更改的文件运行”的设置,现在可以在更短的时间内运行整个代码库。

这对于大型项目当然是如此,在大型项目中,数量级的提升意味着从分钟到秒,再到毫秒。但即使对于小型项目,响应速度的差异——无论是在命令行还是在编辑器中——都令人上瘾。

Formatting a variety of large Python projects via `ruff format`

在几毫秒内格式化超过 2,000,000 行 Python 代码,无需缓存。

和代码检查工具一样,我们对性能的标准是:“快得离谱”“快得过分”“快到我总以为它没运行”“快到我以为它出错了” 等等。

2. 兼容 Black

从一开始,我们的目标就是提供一个 Black 的直接替代品 — 一个项目可以以最小的变动和干扰来采纳的格式化工具。

在对 Django 和 Zulip 等流行 Black 格式化项目进行基准测试时,ruff format 在更改行数方面实现了与 Black 超过 99.9% 的兼容性。将现有项目迁移到 Ruff 的格式化工具时,绝大多数行将以相同方式格式化,仅在细微之处存在一些已知差异

总的来说,我们倾向于模仿 Black 的代码风格 — 除非我们发现有令人信服的理由进行分歧。例如:与 Black 不同,格式化工具在测量行长度时会排除 pragma 注释,这可以防止添加 # noqa 注释导致代码重排,从而避免了添加 # noqa 注释后它在格式化过程中被移动的令人沮丧的循环。

与 Black 类似,格式化工具也实现了单一的代码风格,但 — 与 Black 不同的是 — 它公开了一些额外的配置选项。例如,格式化工具允许用户选择他们偏好的引号和缩进风格

[tool.ruff.format]
quote-style = "single"
indent-style = "tab"

尽管 Black 有一份出色的风格指南,但考虑到两种工具在架构上的差异,要达到这种程度的兼容性非常具有挑战性。我们花费了大量时间进行逆向工程,并投入了一个广泛的测试套件 — 在 Black 自身测试的基础上,增加了对即使是最不切实际的边缘情况的额外覆盖。

可用于生产环境

尽管这是一个 Beta 版本,但我们认为 Ruff 格式化工具已经可用于生产环境。我们已经在生产环境中使用了一段时间,我们的 Alpha 用户也从 GitHubDiscord 获得了反馈 — 包括 Dagster,其单一代码库包含超过 50 个 Python 包和 500,000 行代码。

我们对格式化工具稳定版的目标是增加更多功能以及与代码检查工具更深度的集成。具体来说,稳定版将包括

  • 支持 Black 的预览风格。(Beta 版仅限于支持 Black 的稳定风格。)
  • 在我们的语言服务器和编辑器集成中支持范围格式化。
  • 支持在 f-string 内部进行格式化。

在 Beta 阶段,我们特别关注以下两方面的反馈:(1)格式化工具配置,以及(2)格式化工具与代码检查工具之间更深度的集成。我们期待您的宝贵意见。

Astral 工具链

除了格式化工具本身,本次发布对作为项目的 Ruff 和作为公司的 Astral 来说都具有里程碑意义,原因有二

  1. 这是我们首次推出代码检查工具以外的工具。 格式化工具是一个全新的东西。尽管它与代码检查工具共享一些基础设施(例如,我们的词法分析器和解析器),但发布格式化工具要求我们更新 Ruff 的内部结构、API 和文档,以适应多工具架构 — 这项工作将在我们启动“下一个项目”时继续利用。
  2. 这是我们第一次以团队形式构建新东西。 Ruff 代码检查工具的初稿是由我在一个“山洞”里写出来的。(我们现在已经发展到一个五人核心团队,拥有 290 多名贡献者。)这一次,格式化工具的开发完全由那些不是我的人主导:Micha Reiserkonsti。就我个人而言,看着他们从无到有地创造出如此高质量的产品,我感到非常欣慰 — 我很幸运能称他们为我的同事。

随着我们团队的成长,我们能够承担的工作范围也随之扩大。在接下来的几个月里,我们将继续大力投入代码检查工具和格式化工具的开发,同时启动几项新工作,以追求统一的 Python 工具链。

如果您觉得这类问题令人兴奋:我们正在招聘

致谢

最后,我们要感谢所有直接为 Ruff 格式化工具开发做出贡献的人,包括 Anders KaseorgCalum YoungChris PryerDavid SzottenDimitri PapadopoulosHarutaka KawamuraJeong YunWonJonathan PlasseLouis DispaLuc Khai HaiTom KusonVictor Hugo Gomescosmojgmagic-akariqdegraaf,以及那些提供早期反馈的社区成员。

我们还要感谢更广泛社区中的一些个人: