Ruff Linter
Ruff Linter 是一个速度极快的 Python linter,旨在作为 Flake8 (以及数十个插件)、isort、pydocstyle、pyupgrade、autoflake 等的直接替代品。
ruff check
ruff check
是 Ruff linter 的主要入口点。它接受文件或目录列表,并检查所有发现的 Python 文件,可以选择修复任何可修复的错误。在检查目录时,Ruff 会在该目录及其所有子目录中递归搜索 Python 文件
$ ruff check # Lint files in the current directory.
$ ruff check --fix # Lint files in the current directory and fix any fixable errors.
$ ruff check --watch # Lint files in the current directory and re-lint on change.
$ ruff check path/to/code/ # Lint files in `path/to/code`.
有关支持的完整选项列表,请运行 ruff check --help
。
规则选择
启用规则的集合通过 lint.select
、lint.extend-select
和 lint.ignore
设置进行控制。
Ruff 的 linter 镜像了 Flake8 的规则代码系统,其中每个规则代码都由一个一到三个字母的前缀,后跟三个数字(例如,F401
)组成。前缀指示规则的“来源”(例如,F
代表 Pyflakes,E
代表 pycodestyle,ANN
代表 flake8-annotations)。
像 lint.select
和 lint.ignore
这样的规则选择器接受完整的规则代码(例如,F401
)或任何有效的前缀(例如,F
)。例如,给定以下配置文件
Ruff 将启用所有带有 E
(pycodestyle) 或 F
(Pyflakes) 前缀的规则,但 F401
除外。有关通过 pyproject.toml
配置 Ruff 的更多信息,请参见 配置 Ruff。
作为一种特殊情况,Ruff 还支持 ALL
代码,该代码启用所有规则。请注意,某些 pydocstyle 规则会冲突(例如,D203
和 D211
),因为它们代表了替代的文档字符串格式。启用 ALL
时,Ruff 将自动禁用任何冲突的规则。
如果您想知道如何配置 Ruff,这里有一些 推荐的指南
- 首选
lint.select
而不是lint.extend-select
以使您的规则集明确。 - 谨慎使用
ALL
。启用ALL
将在您每次升级时隐式启用新规则。 - 从一小部分规则 (
select = ["E", "F"]
) 开始,并一次添加一个类别。例如,您可以考虑扩展到select = ["E", "F", "B"]
以启用流行的 flake8-bugbear 扩展。
例如,启用一些最流行的规则(而又不过于迂腐)的配置可能如下所示
要解析启用的规则集,Ruff 可能需要协调来自各种来源的 lint.select
和 lint.ignore
,包括当前的 pyproject.toml
、任何继承的 pyproject.toml
文件和 CLI(例如,--select
)。
在这些情况下,Ruff 使用“最高优先级”select
作为规则集的基础,然后应用 extend-select
和 ignore
调整。 CLI 选项的优先级高于 pyproject.toml
选项,而当前 pyproject.toml
文件的优先级高于任何继承的 pyproject.toml
文件。
例如,给定以下配置文件
运行 ruff check --select F401
将导致 Ruff 强制执行 F401
,而不执行其他规则。
运行 ruff check --extend-select B
将导致 Ruff 强制执行 E
、F
和 B
规则,但 F401
除外。
修复
Ruff 支持自动修复各种 lint 错误。例如,Ruff 可以删除未使用的导入、重新格式化文档字符串、重写类型注解以使用更新的 Python 语法等。
要启用修复,请将 --fix
标志传递给 ruff check
默认情况下,Ruff 将修复所有可用的安全修复的违规行为;要确定规则是否支持修复,请参见 规则。
修复安全性
Ruff 将修复标记为“安全”和“不安全”。应用安全修复时,代码的含义和意图将得以保留,但应用不安全修复时,含义可能会更改。
具体来说,不安全修复可能会导致运行时行为发生变化、删除注释或两者兼而有之,而安全修复旨在保留运行时行为,并且仅在删除整个语句或表达式时(例如,删除未使用的导入)才删除注释。
例如,unnecessary-iterable-allocation-for-first-element
(RUF015
) 是一条规则,用于检查可能导致性能问题的 list(...)[0]
用法。该修复将此模式替换为 next(iter(...))
,这可以显著提高速度
$ python -m timeit "head = next(iter(range(99999999)))"
5000000 loops, best of 5: 70.8 nsec per loop
但是,当集合为空时,此引发的异常将从 IndexError
更改为 StopIteration
$ python -c 'list(range(0))[0]'
Traceback (most recent call last):
File "<string>", line 1, in <module>
IndexError: list index out of range
$ python -c 'next(iter(range(0)))[0]'
Traceback (most recent call last):
File "<string>", line 1, in <module>
StopIteration
由于异常类型的更改可能会破坏上游的错误处理,因此此修复被归类为不安全。
默认情况下,Ruff 仅启用安全修复。可以通过在配置文件中设置 unsafe-fixes
或将 --unsafe-fixes
标志传递给 ruff check
来启用不安全修复
默认情况下,当不安全修复可用但未启用时,Ruff 将显示提示。可以通过将 unsafe-fixes
设置设置为 false
或使用 --no-unsafe-fixes
标志来使该建议静默。
可以使用 lint.extend-safe-fixes
和 lint.extend-unsafe-fixes
设置按规则调整修复的安全性。
例如,以下配置会将 F601
的不安全修复提升为安全修复,并将 UP034
的安全修复降级为不安全修复
您也可以使用前缀来选择规则,例如,F
可用于将 Pyflakes 中所有规则的修复提升为安全。
注意
使用 json
输出格式时,Ruff 将始终显示所有修复。每个修复的安全性都在 applicability
字段下可用。
禁用修复
要限制 Ruff 应修复的规则集,请使用 lint.fixable
或 lint.extend-fixable
和 lint.unfixable
设置。
例如,以下配置将启用除 unused-imports
(F401
) 之外的所有规则的修复
相反,以下配置将仅启用 F401
的修复
错误抑制
Ruff 支持多种抑制 lint 错误的机制,无论它们是误报还是允许的违规行为。
要完全忽略 lint 规则,请通过 lint.ignore
设置将其添加到“ignore”列表中,无论是在命令行中还是在您的 pyproject.toml
或 ruff.toml
文件中。
要内联抑制违规行为,Ruff 使用类似于 Flake8 的 noqa
系统。要忽略单个违规行为,请将 # noqa: {code}
添加到行尾,如下所示
# Ignore F841.
x = 1 # noqa: F841
# Ignore E741 and F841.
i = 1 # noqa: E741, F841
# Ignore _all_ violations.
x = 1 # noqa
对于多行字符串(如文档字符串),noqa
指令应位于字符串的末尾(在结束的三引号之后),并将应用于整个字符串,如下所示
"""Lorem ipsum dolor sit amet.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.
""" # noqa: E501
对于导入排序,noqa
应位于导入块中第一行的末尾,并将应用于块中的所有导入,如下所示
要忽略整个文件中的所有违规行为,请在文件中的任何位置添加行 # ruff: noqa
,最好是在顶部附近,如下所示
要忽略整个文件中的特定规则,请在文件中的任何位置添加行 # ruff: noqa: {code}
,最好是在顶部附近,如下所示
或者参见 lint.per-file-ignores
设置,该设置从您的 pyproject.toml
或 ruff.toml
文件中启用相同的功能。
全局 noqa
注释必须位于其自己的行上,以消除与忽略单行违规行为的注释的歧义。
请注意,Ruff 还将尊重 Flake8 的 # flake8: noqa
指令,并将其视为等同于 # ruff: noqa
。
完整的抑制注释规范
完整的规范如下
- 内联的 blanket
noqa
注释由不区分大小写的#noqa
匹配给出,在#
符号后带有可选的空格,后跟:注释的结尾、新注释的开头 (#
) 或空格后跟除:
之外的任何字符。 - 内联规则抑制首先通过不区分大小写的
#noqa
匹配给出,在#
符号后带有可选的空格,在noqa
后带有可选的空格,后跟符号:
。在此之后,我们应该有一个规则代码列表,该列表由大写 ASCII 字符后跟 ASCII 数字的序列给出,并用空格或逗号分隔。列表在最后一个有效代码处结束。我们将尝试解释缺少分隔符的规则(例如F401F841
),但在此情况下将发出警告。 - 文件级豁免注释由区分大小写的
#ruff:
或#flake8:
匹配给出,在#
和:
之前带有可选的空格,后跟可选的空格和不区分大小写的noqa
匹配。之后,规范与内联情况相同。
检测未使用的抑制注释
Ruff 实现了一个特殊的规则 unused-noqa
,在 RUF100
代码下,用于强制您的 noqa
指令“有效”,即它们说它们忽略的违规行为实际上是在该行上触发的(因此被抑制)。要标记未使用的 noqa
指令,请运行:ruff check /path/to/file.py --extend-select RUF100
。
Ruff 还可以通过其修复功能删除任何未使用的 noqa
指令。要删除任何未使用的 noqa
指令,请运行:ruff check /path/to/file.py --extend-select RUF100 --fix
。
插入必要的抑制注释
Ruff 可以自动添加 noqa
指令到所有包含违规行为的行,这在将新代码库迁移到 Ruff 时非常有用。要自动添加 noqa
指令到所有相关行(带有适当的规则代码),请运行:ruff check /path/to/file.py --add-noqa
。
操作注释
Ruff 尊重 isort 的 操作注释 (# isort: skip_file
, # isort: on
, # isort: off
, # isort: skip
和 # isort: split
),这可以有选择地为代码块和其他内联配置启用和禁用导入排序。
Ruff 还将尊重这些操作注释的变体,带有 # ruff:
前缀(例如,# ruff: isort: skip_file
, # ruff: isort: on
等)。这些变体更清楚地表明操作注释是为 Ruff 设计的,但在功能上与 isort 变体等效。
与 isort 不同,Ruff 不尊重文档字符串中的操作注释。
有关更多信息,请参见 isort 文档。
退出码
默认情况下,ruff check
以以下状态代码退出
0
如果未发现违规行为,或者如果所有存在的违规行为都已自动修复。1
如果发现违规行为。2
如果 Ruff 由于无效的配置、无效的 CLI 选项或内部错误而异常终止。
此约定镜像了 ESLint、Prettier 和 RuboCop 等工具。
ruff check
支持两个命令行标志,这些标志会更改其退出代码行为
--exit-zero
将导致 Ruff 即使发现违规行为也以状态代码0
退出。请注意,如果 Ruff 异常终止,它仍然会以状态代码2
退出。--exit-non-zero-on-fix
将导致 Ruff 如果发现违规行为以状态代码1
退出,即使所有此类违规行为都已自动修复。请注意,即使在修复后没有剩余违规行为,使用--exit-non-zero-on-fix
也可能导致非零退出代码。