本教程将带你把 Ruff 的代码检查器和格式化器集成到项目中。更详细的介绍见配置 Ruff。
开始使用
首先用 uv 初始化项目:
$ uv init --lib numbers
这个命令创建的 Python 项目结构如下:
numbers
├── README.md
├── pyproject.toml
└── src
└── numbers
├── __init__.py
└── py.typed
接下来清空 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 add --dev 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.
Ruff 找到了一个未使用的导入,这是 Python 代码中常见的错误。Ruff 认为它是“可修复”的错误,因此可以运行 ruff check --fix 自动解决:
$ uv run ruff check --fix
Found 1 error (1 fixed, 0 remaining).
运行 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 默认在当前目录运行,也可以指定要检查的路径:
$ uv run ruff check src/numbers/calculate.py
项目通过 ruff check 后,就可以通过 ruff format 运行 Ruff 格式化器:
$ uv run ruff format
1 file reformatted
运行 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 的默认配置。接下来看看怎样自定义它的行为。
配置
为了确定每个 Python 文件适用的设置,Ruff 会在该文件所在目录或其任意父目录中,查找首先遇到的 pyproject.toml、ruff.toml 或 .ruff.toml。
在项目根目录中的配置文件添加以下设置:
pyproject.toml
[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.toml
# Set the maximum line length to 79.
line-length = 79
[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 字符的行宽限制:
$ uv run ruff check
src/numbers/calculate.py:5:80: E501 Line too long (90 > 79)
Found 1 error.
支持的全部设置见设置。对于这个项目,还需要明确最低支持的 Python 版本:
pyproject.toml
[project]
# Support Python 3.10+.
requires-python = ">=3.10"
[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.
extend-select = ["E501"]
ruff.toml
# Support Python 3.10+.
target-version = "py310"
# Set the maximum line length to 79.
line-length = 79
[lint]
# Add the `line-too-long` rule to the enforced rule set.
extend-select = ["E501"]
选择规则
Ruff 支持分布于 50 多个内置插件的900 多条代码检查规则,但合适的规则集合取决于项目需求:有些规则可能太严格,有些只适用于特定框架,等等。
默认情况下,Ruff 启用 F、E、B、UP 和 RUF 等类别中的规则,同时省略与 ruff format 或 Black 等格式化器重叠的风格规则。
如果第一次引入代码检查器,默认规则集是很好的起点:无需配置即可发现广泛的常见错误,例如未使用的导入。完整列表见默认规则。
如果从其他代码检查器迁移到 Ruff,可以启用与先前配置等价的规则。例如,想执行 pyupgrade 规则,可以使用以下配置:
pyproject.toml
[project]
requires-python = ">=3.10"
[tool.ruff.lint]
extend-select = [
"UP", # pyupgrade
]
ruff.toml
target-version = "py310"
[lint]
extend-select = [
"UP", # 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.
随着时间推移,我们可能会启用更多规则。例如,希望所有函数都具有文档字符串:
pyproject.toml
[project]
requires-python = ">=3.10"
[tool.ruff.lint]
extend-select = [
"UP", # pyupgrade
"D", # pydocstyle
]
[tool.ruff.lint.pydocstyle]
convention = "google"
ruff.toml
target-version = "py310"
[lint]
extend-select = [
"UP", # pyupgrade
"D", # pydocstyle
]
[lint.pydocstyle]
convention = "google"
再次运行 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 违规添加指令:
$ uv run ruff check --select UP035 --add-noqa .
Added 1 noqa directive.
运行 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: ignore[...] 注释,则使用 --add-ignore 标志。在预览模式中,--add-ignore 使用可读的规则名称代替规则代码。
集成
本教程主要介绍 Ruff 的命令行界面,但也可以通过 ruff-pre-commit 将 Ruff 用作 pre-commit 钩子:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.16.10
hooks:
# Run the linter.
- id: ruff-check
# Run the formatter.
- id: ruff-format
Ruff 还可以集成到你选择的编辑器。更多信息见编辑器章节。
其他集成方式见集成章节。











暂无评论内容