教程
本教程将引导你完成将 Ruff 的代码检查器(Linter)和格式化工具(Formatter)集成到项目中的过程。如需更详细的概述,请参阅 配置 Ruff。
入门指南
首先,我们将使用 uv 初始化一个项目
此命令将创建一个具有以下结构的 Python 项目
接下来,我们将清空 src/numbers/__init__.py 中的自动生成内容,并创建 src/numbers/calculate.py,代码如下
from typing import Iterable
import os
def sum_even_numbers(numbers: Iterable[int]) -> int:
"""Given an iterable of integers, return the sum of all even numbers in the iterable."""
return sum(
num for num in numbers
if num % 2 == 0
)
然后,我们将 Ruff 添加到项目中
接着,我们可以通过 uv run ruff check 在项目中运行 Ruff 代码检查器
$ uv run ruff check
src/numbers/calculate.py:3:8: F401 [*] `os` imported but unused
Found 1 error.
[*] 1 fixable with the `--fix` option.
注意
作为 uv run 的替代方案,你也可以通过激活项目的虚拟环境(Linux 和 macOS 上为 source .venv/bin/activate,Windows 上为 .venv\Scripts\activate)并直接运行 ruff check 来使用 Ruff。
Ruff 发现了一个未使用的导入,这是 Python 代码中的常见错误。Ruff 认为这是一个“可修复”的错误,因此我们可以通过运行 ruff check --fix 自动解决此问题
运行 git diff 可见以下变更
--- a/src/numbers/calculate.py
+++ b/src/numbers/calculate.py
@@ -1,7 +1,5 @@
from typing import Iterable
-import os
-
def sum_even_numbers(numbers: Iterable[int]) -> int:
"""Given an iterable of integers, return the sum of all even numbers in the iterable."""
return sum(
num for num in numbers
if num % 2 == 0
)
注意,Ruff 默认在当前目录运行,但你可以传入特定路径进行检查
现在我们的项目已通过 ruff check,我们可以通过 ruff format 运行 Ruff 格式化工具
运行 git diff 显示 sum 调用已被重新格式化,以符合默认的 88 字符行长度限制
--- a/src/numbers/calculate.py
+++ b/src/numbers/calculate.py
@@ -3,7 +3,4 @@ from typing import Iterable
def sum_even_numbers(numbers: Iterable[int]) -> int:
"""Given an iterable of integers, return the sum of all even numbers in the iterable."""
- return sum(
- num for num in numbers
- if num % 2 == 0
- )
+ return sum(num for num in numbers if num % 2 == 0)
到目前为止,我们一直使用 Ruff 的默认配置。接下来让我们看看如何自定义 Ruff 的行为。
配置
为了确定每个 Python 文件的适当设置,Ruff 会在该文件所在的目录或任何父目录中查找第一个 pyproject.toml、ruff.toml 或 .ruff.toml 文件。
要配置 Ruff,我们将在项目根目录的配置文件中添加以下内容
[tool.ruff]
# Set the maximum line length to 79.
line-length = 79
[tool.ruff.lint]
# Add the `line-too-long` rule to the enforced rule set. By default, Ruff omits rules that
# overlap with the use of a formatter, like Black, but we can override this behavior by
# explicitly adding the rule.
extend-select = ["E501"]
再次运行 Ruff,我们发现它现在强制执行最大行宽,限制为 79
有关支持设置的完整枚举,请参阅 设置。对于我们的项目,需要特别注意支持的最低 Python 版本
规则选择
Ruff 支持 超过 800 条代码检查规则,分布在 50 多个内置插件中。确定合适的规则集取决于你项目的需求:有些规则可能过于严格,有些则是特定框架专用的,等等。
默认情况下,Ruff 会启用 Flake8 的 F 规则以及 E 规则的子集,同时省略任何与格式化工具(如 ruff format 或 Black)重叠的样式规则。
如果你是首次引入代码检查器,默认规则集是一个很好的起点:它精简且专注,能够在零配置的情况下捕获各种常见错误(例如未使用的导入)。
如果你是从其他代码检查器迁移到 Ruff,你可以启用与之前配置中等效的规则。例如,如果我们想强制执行 pyupgrade 规则,可以将配置文件设置为以下内容
如果我们再次运行 Ruff,会发现它现在强制执行 pyupgrade 规则。特别是,Ruff 会标记出对已弃用的 typing.Iterable 的使用,建议改为 collections.abc.Iterable
$ uv run ruff check
src/numbers/calculate.py:1:1: UP035 [*] Import from `collections.abc` instead: `Iterable`
Found 1 error.
[*] 1 fixable with the `--fix` option.
随着时间的推移,我们可能会选择强制执行额外的规则。例如,我们可能希望强制要求所有函数都包含文档字符串
如果我们再次运行 Ruff,会发现它现在强制执行 pydocstyle 规则
$ uv run ruff check
src/numbers/__init__.py:1:1: D104 Missing docstring in public package
src/numbers/calculate.py:1:1: UP035 [*] Import from `collections.abc` instead: `Iterable`
|
1 | from typing import Iterable
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035
|
= help: Import from `collections.abc`
src/numbers/calculate.py:1:1: D100 Missing docstring in public module
Found 3 errors.
[*] 1 fixable with the `--fix` option.
忽略错误
任何检查规则都可以通过在相关行添加 # noqa 注释来忽略。例如,让我们忽略 Iterable 导入的 UP035 规则
from typing import Iterable # noqa: UP035
def sum_even_numbers(numbers: Iterable[int]) -> int:
"""Given an iterable of integers, return the sum of all even numbers in the iterable."""
return sum(num for num in numbers if num % 2 == 0)
再次运行 ruff check,我们会发现它不再标记 Iterable 导入
$ uv run ruff check
src/numbers/__init__.py:1:1: D104 Missing docstring in public package
src/numbers/calculate.py:1:1: D100 Missing docstring in public module
Found 2 errors.
如果我们想忽略整个文件的某个规则,可以在文件中的任何位置添加 # ruff: noqa: {code},最好放在顶部,如下所示
# ruff: noqa: UP035
from typing import Iterable
def sum_even_numbers(numbers: Iterable[int]) -> int:
"""Given an iterable of integers, return the sum of all even numbers in the iterable."""
return sum(num for num in numbers if num % 2 == 0)
有关忽略错误的更深入说明,请参阅 错误抑制。
添加规则
当在现有代码库中启用新规则时,你可能希望忽略该规则的 现有 所有违规情况,而仅专注于在未来强制执行。
Ruff 通过 --add-noqa 标志支持此工作流,它会根据现有违规情况为每一行添加 # noqa 指令。我们可以将 --add-noqa 与 --select 命令行标志结合使用,为所有现有的 UP035 违规添加 # noqa 指令
运行 git diff 可见以下变更
diff --git a/numbers/src/numbers/calculate.py b/numbers/src/numbers/calculate.py
index 71fca60c8d..e92d839f1b 100644
--- a/numbers/src/numbers/calculate.py
+++ b/numbers/src/numbers/calculate.py
@@ -1,4 +1,4 @@
-from typing import Iterable
+from typing import Iterable # noqa: UP035
集成
本教程重点介绍了 Ruff 的命令行界面,但 Ruff 也可以通过 ruff-pre-commit 作为 pre-commit 钩子使用
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.15.7
hooks:
# Run the linter.
- id: ruff-check
# Run the formatter.
- id: ruff-format
Ruff 也可以集成到你选择的编辑器中。更多信息请参阅 编辑器 部分。
有关其他集成,请参阅 集成 部分。