Ruff:用 Rust 重写 Python 工具链,一个二进制替代 Flake8、Black 和 isort
Ruff 是一款用 Rust 编写的 Python 代码检查与格式化工具,内置 900 多条规则,兼容 Flake8、isort 和 Black,还能自动修复错误。
秒懂
- 它是什么?
- Ruff 是一个用 Rust 编写的 Python linter 和格式化器,号称比现有工具快 10 到 100 倍,并整合了多种工具的功能。本文分析它的架构、配置方式、适用边界,以及它是否值得取代你现有的工具链。
- 适合谁用?
- Ruff 适合那些受困于多工具配置和慢速 lint 的 Python 项目,尤其是大型代码库或 CI 管道。它不适合已经深度依赖某个特定 Flake8 插件且该插件未被原生重写的项目,也不适合需要严格保持 Black 格式化细节的项目。
- 能商用吗?
- 可以。MIT 是宽松许可证:你可以使用、修改并销售基于它的软件,只需保留版权和许可证声明。
- 还在维护吗?
- 在维护。仓库在最近一天内有新的提交。
- 用什么语言写的?
- 主要是 Rust(依据 GitHub 的语言统计)。
以上回答依据项目的 GitHub 数据(最近同步于 2026年9月15日)和我们的分析,不构成法律意见。
开源项目深度解析
一个二进制,替代五个工具
Python 项目的静态检查通常要拼装多个工具:Flake8 管风格,Black 管格式化,isort 管导入排序,pydocstyle 管文档字符串,pyupgrade 管语法升级。每个工具都有自己的配置、缓存和调用方式,CI 里串起来跑一遍,时间就上去了。Ruff 的目标是把这些功能塞进一个 Rust 写的二进制里。README 明确说它可以替换 Flake8(含插件)、Black、isort、pydocstyle、pyupgrade 和 autoflake。这不是把外部工具包一层壳,而是用 Rust 原生重写了超过 900 条规则。对维护多仓库的团队来说,统一工具链意味着少一份配置、少一种依赖、少一个出错的环节。
速度从哪里来:缓存、并行与 Rust
Ruff 的卖点是快,README 声称比 Flake8 和 Black 快 10 到 100 倍。这个数字来自 Rust 的执行效率,也来自内置缓存机制。文档说缓存可以避免重新分析未改变的文件,这意味着在本地开发时,第二次运行几乎瞬间完成。另一个关键点是并行处理,Rust 的线程模型让 Ruff 能充分利用多核 CPU。引用的用户反馈提到,在 25 万行的代码库上,pylint 需要 2.5 分钟,而 Ruff 扫描整个代码库只用 0.4 秒。这些是使用者的报告,不是官方基准,但方向一致:Ruff 把 lint 从「等一会儿」变成「即时反馈」。这种速度让开发者愿意把 Ruff 放进 commit hook,而不是只在 CI 里跑。
安装与启动:从 uvx 到独立安装器
Ruff 的安装方式很多,但 README 推荐用 uv 工具链。最简单的临时调用是 `uvx ruff@0.16.5 check`,它会在当前目录检查所有文件,`uvx ruff@0.16.5 format` 则格式化所有文件。如果你想全局安装,可以用 `uv tool install ruff@latest`,或者用 pip 和 pipx。从 0.5.0 开始,Ruff 提供了独立安装脚本:macOS 和 Linux 上运行 `curl -LsSf https://astral.sh/ruff/install.sh | sh`,Windows 上运行 PowerShell 命令。Homebrew 和 Conda 也支持。这种多渠道安装降低了入门门槛,但也意味着版本碎片化,不同环境可能跑到不同版本。
配置:pyproject.toml 里的单一入口
Ruff 的配置集中在 `pyproject.toml` 的 `[tool.ruff]` 段,这符合现代 Python 项目的习惯。文档提到它支持层级和级联配置,这对 monorepo 很友好:根目录设置全局规则,子项目可以覆盖或追加。配置项包括 `select` 和 `ignore` 来启用或禁用规则,还有针对 formatter 的选项。关键点是,Ruff 的规则编号与 Flake8 插件对应,比如 flake8-bugbear 的规则以 B 开头。这意味着迁移时,你可以对照现有 Flake8 配置,把插件规则映射到 Ruff 的规则集。但 README 没有列出完整的配置键,实际使用时需要查阅官方文档。对于已经有复杂 Flake8 配置的项目,迁移不是零成本。
规则覆盖的边界:不是所有插件都被重写
Ruff 原生重写了超过 900 条规则,包括 flake8-bugbear 这类流行插件。但「超过 900 条」不等于「覆盖所有 Flake8 插件」。Flake8 生态里有大量小众插件,Ruff 未必都实现了。如果你依赖某个特定插件的检查逻辑,迁移前必须验证。另一个潜在问题是规则的行为差异。Ruff 声称与 Flake8 有「drop-in parity」,但这是官方说法,实际规则细节可能不同。比如某些规则的误报率或修复建议可能不一致。如果你在一个严格遵循特定 lint 风格的项目上,直接切换 Ruff 可能会导致新的警告或漏报。
格式化器:Black 兼容但非完全相同
Ruff 的 formatter 对标 Black,但 README 用「drop-in parity」这个词,而不是「完全一致」。这意味着大部分代码格式化结果与 Black 相同,但边缘情况可能有差异。Black 的格式化风格是「无配置的固执己见」,而 Ruff 的 formatter 允许一定程度的配置,这本身就是一种偏离。如果你现有的代码库已经用 Black 格式化过,切换到 Ruff format 后,可能会产生一些 diff。这些 diff 不一定是错的,但会污染你的 git 历史。对于追求格式化一致性的团队,需要在切换前运行一次 `ruff format --check`,看看实际差异有多少。
维护与升级:活跃开发的双刃剑
Ruff 的发布节奏很快,从 2026 年 8 月的版本号看,0.16.5 到 0.16.4 只隔了一周。这反映了项目的活跃度,但也带来升级成本。每次新版本可能引入新规则、改变默认行为或修复 bug。对于依赖稳定工具链的团队,频繁升级意味着需要持续关注 changelog。许可证是 MIT,这对商业项目友好,没有 copyleft 义务。但注意,Ruff 由 Astral 公司维护,这家公司也开发 uv 和 ty。如果你不喜欢把核心工具链押注在一家商业公司上,这可能是一个考量点。不过 MIT 许可证允许你 fork 并自行维护,只是实际成本很高。
替代方案:Flake8 生态与 Black 的组合
Ruff 的主要替代方案是传统的 Flake8 加 Black 加 isort 组合。这个组合的优势是成熟和可扩展:Flake8 的插件机制允许你添加任意检查器,Black 的格式化风格是事实标准。缺点是性能差,配置分散,而且每个工具都需要单独维护。另一个替代是 pylint,它更严格、检查更多逻辑问题,但速度更慢。Ruff 的定位不是替代 pylint 的全部功能,而是替代那些「快而浅」的检查。如果你的项目需要 pylint 级别的深度分析,Ruff 可能不够。选择的关键是你更看重速度还是深度。
编辑结论
Ruff 适合那些受困于多工具配置和慢速 lint 的 Python 项目,尤其是大型代码库或 CI 管道。它不适合已经深度依赖某个特定 Flake8 插件且该插件未被原生重写的项目,也不适合需要严格保持 Black 格式化细节的项目。采用前,你应该先在自己的代码库上运行 `ruff check` 和 `ruff format`,对比输出与现有工具的差异,特别是检查规则覆盖和格式化的一致性。Ruff 的配置通过 `pyproject.toml` 的 `[tool.ruff]` 段完成,你需要验证 `select` 和 `ignore` 列表能否覆盖你现有的 Flake8 插件规则。由于 Ruff 仍在积极开发,版本更新频繁,升级前应查看 changelog,确认行为变化。MIT 许可证允许自由使用,但你需要自行决定是否信任 Astral 公司的维护节奏。
社区笔记