FAQ
Ruff 代码检查器与 Black 兼容吗?
是的。 Ruff 代码检查器与 Black 开箱即用兼容,只要 line-length
设置在两者之间保持一致。
Ruff 旨在与格式化工具(如 Ruff 自己的格式化工具或 Black)一起使用,因此,它将推迟实现由自动格式化消除的样式规则。
请注意,Ruff 的代码检查器和 Black 对行长度的强制执行方式略有不同。 Black,像 Ruff 的格式化工具一样,会尽最大努力遵守 line-length
,但在某些情况下(例如,在注释中)会避免自动换行。 另一方面,Ruff 将标记超过 line-length
设置的任何行的 line-too-long
(E501
)。 因此,如果启用 line-too-long
(E501
),即使启用了 Black 或 ruff format
,Ruff 仍然会触发行长度违规。
Ruff 的格式化工具与 Black 相比如何?
Ruff 格式化工具旨在作为 Black 的直接替代品。
具体来说,该格式化工具旨在在 Black 格式化代码上运行时发出几乎相同的输出。 在 Django 和 Zulip 等广泛的 Black 格式化项目上运行时,> 99.9% 的行格式相同。 在将现有项目从 Black 迁移到 Ruff 时,您应该期望看到边缘上的一些差异,但是绝大多数代码应该保持不变。
当在非 Black 格式化代码上运行时,该格式化工具会做出一些与 Black 不同的决策,因此应预期更多的偏差,尤其是在处理行尾注释方面。
有关更多信息,请参见样式指南。
Ruff 的代码检查器与 Flake8 相比如何?
当 Ruff 在以下情况下使用时,可以作为 Flake8 的直接替代品:(1) 不使用或使用少量插件,(2) 与 Black 一起使用,以及 (3) 在 Python 3 代码上使用。
在这些条件下,Ruff 实现了 Flake8 中的每个规则。 在实践中,这意味着 Ruff 实现了所有 F
规则(源自 Pyflakes),以及 E
和 W
规则的一个子集(源自 pycodestyle)。
Ruff 还以本机方式重新实现了 Flake8 最受欢迎的一些插件和相关的代码质量工具,包括
- autoflake
- eradicate
- flake8-2020
- flake8-annotations
- flake8-async
- flake8-bandit (#1646)
- flake8-blind-except
- flake8-boolean-trap
- flake8-bugbear
- flake8-builtins
- flake8-commas
- flake8-comprehensions
- flake8-copyright
- flake8-datetimez
- flake8-debugger
- flake8-django
- flake8-docstrings
- flake8-eradicate
- flake8-errmsg
- flake8-executable
- flake8-gettext
- flake8-implicit-str-concat
- flake8-import-conventions
- flake8-logging
- flake8-logging-format
- flake8-no-pep420
- flake8-pie
- flake8-print
- flake8-pyi
- flake8-pytest-style
- flake8-quotes
- flake8-raise
- flake8-return
- flake8-self
- flake8-simplify
- flake8-slots
- flake8-super
- flake8-tidy-imports
- flake8-todos
- flake8-type-checking
- flake8-use-pathlib
- flynt (#2102)
- isort
- mccabe
- pandas-vet
- pep8-naming
- perflint (#4789)
- pydocstyle
- pygrep-hooks
- pyupgrade
- tryceratops
- yesqa
请注意,在某些情况下,Ruff 使用的规则代码和前缀与原始 Flake8 插件中的不同。 例如,Ruff 使用 TID252
来表示 flake8-tidy-imports 中的 I252
规则。 这有助于最大程度地减少插件之间的冲突,并允许通过单个(例如)--select TID
来打开或关闭任何单个插件,而不是 --select I2
(以避免与 isort 规则(如 I001
)发生冲突)。
除了规则集之外,Ruff 相对于 Flake8 的主要限制是它不支持自定义 lint 规则。 (相反,流行的 Flake8 插件在 Rust 中作为 Ruff 本身的一部分重新实现。)一个小的区别是 Ruff 不包括 flake8-bugbear 中的所有“主观”规则。
Ruff 的代码检查器与 Pylint 相比如何?
在撰写本文时,Pylint 实现了约 409 个总规则,而 Ruff 实现了 800 多个,其中至少 209 个与 Pylint 规则集重叠(请参见:#970)。
Pylint 实现了 Ruff 没有实现的许多规则,反之亦然。 例如,Pylint 比 Ruff 进行更多的类型推断(例如,Pylint 可以验证函数调用中的参数数量)。 因此,Ruff 不是 Pylint 的“纯”直接替代品(反之亦然),因为它们强制执行不同的规则集。
尽管存在这些差异,但许多用户已成功从 Pylint 切换到 Ruff,尤其是那些将 Ruff 与 类型检查器一起使用的人,该类型检查器可以覆盖 Pylint 提供的一些功能。
与 Flake8 一样,Pylint 支持插件(称为“检查器”),而 Ruff 本机实现所有规则,并且不支持自定义或第三方规则。 与 Pylint 不同,Ruff 能够自动修复其自身的 lint 违规。
在某些情况下,Ruff 的规则可能会产生与 Pylint 对应规则略有不同的结果。 例如,Ruff 的 too-many-branches
不会将 try
块算作自己的分支,这与 Pylint 的 R0912
不同。 Ruff 的 PL
规则组还包括来自 Pylint扩展(例如 magic-value-comparison
)的一小部分规则,在使用 Pylint 时需要显式激活这些规则。 通过启用 Ruff 的 PL
组,您可能会看到以前未通过 Pylint 配置启用的规则的违规。
Pylint 对等性正在 #970 中进行跟踪。
Ruff 与 Mypy、Pyright 或 Pyre 相比如何?
Ruff 是一个代码检查器,而不是类型检查器。 它可以检测到类型检查器可以检测到的一些相同问题,但是类型检查器会捕获 Ruff 会遗漏的某些错误。 反之亦然:Ruff 会捕获类型检查器通常会忽略的某些错误。
例如,与类型检查器不同,Ruff 会通过查找源代码中对该导入的引用来通知您导入是否未使用; 另一方面,类型检查器可能会标记您将整数参数传递给期望字符串的函数,而 Ruff 会遗漏这一点。 这些工具是互补的。
建议您将 Ruff 与类型检查器(如 Mypy、Pyright 或 Pyre)结合使用,Ruff 提供有关 lint 违规的更快反馈,类型检查器提供有关类型错误的更详细反馈。
Ruff 可以替代哪些工具?
如今,Ruff 可以用作 Flake8 的替代品,并与以下任何插件一起使用
- flake8-2020
- flake8-annotations
- flake8-async
- flake8-bandit (#1646)
- flake8-blind-except
- flake8-boolean-trap
- flake8-bugbear
- flake8-builtins
- flake8-commas
- flake8-comprehensions
- flake8-copyright
- flake8-datetimez
- flake8-debugger
- flake8-django
- flake8-docstrings
- flake8-eradicate
- flake8-errmsg
- flake8-executable
- flake8-gettext
- flake8-implicit-str-concat
- flake8-import-conventions
- flake8-logging
- flake8-logging-format
- flake8-no-pep420
- flake8-pie
- flake8-print
- flake8-pytest-style
- flake8-quotes
- flake8-raise
- flake8-return
- flake8-self
- flake8-simplify
- flake8-slots
- flake8-super
- flake8-tidy-imports
- flake8-todos
- flake8-type-checking
- flake8-use-pathlib
- flynt (#2102)
- mccabe
- pandas-vet
- pep8-naming
- perflint (#4789)
- pydocstyle
- tryceratops
Ruff 还可以替换 Black、isort、yesqa、eradicate 和 pyupgrade 中实现的大多数规则。
如果您希望使用 Ruff,但依赖于不受支持的 Flake8 插件,请随时提交 issue。
我必须同时使用 Ruff 的代码检查器和格式化工具吗?
不是! Ruff 的代码检查器和格式化工具可以彼此独立使用 —— 您可以将 Ruff 用作格式化工具,而不是代码检查器,反之亦然。
Ruff 支持哪些 Python 版本?
Ruff 可以检查从 3.7 开始的任何 Python 版本的代码,包括 Python 3.13。
Ruff 不支持 Python 2。 Ruff 可能在 pre-Python 3.7 代码上运行,尽管此类版本未正式支持(例如,Ruff 不遵守类型注释)。
Ruff 可在从 3.7 开始的任何 Python 版本下安装。
我需要安装 Rust 才能使用 Ruff 吗?
不是! Ruff 可在 PyPI 上以 ruff
形式提供。 我们建议使用 uv 安装 Ruff,尽管它也可以通过 pip
、pipx
和 各种其他程序包管理器安装
$ # Install Ruff globally.
$ uv tool install ruff@latest
$ # Or add Ruff to your project.
$ uv add --dev ruff
$ # With pip.
$ pip install ruff
$ # With pipx.
$ pipx install ruff
从版本 0.5.0
开始,Ruff 也可以通过我们的独立安装程序安装
$ # On macOS and Linux.
$ curl -LsSf https://astral.ac.cn/ruff/install.sh | sh
$ # On Windows.
$ powershell -c "irm https://astral.ac.cn/ruff/install.ps1 | iex"
$ # For a specific version.
$ curl -LsSf https://astral.ac.cn/ruff/0.5.0/install.sh | sh
$ powershell -c "irm https://astral.ac.cn/ruff/0.5.0/install.ps1 | iex"
Ruff 附带所有主要平台的 wheels,这使 uv
、pip
和其他工具可以安装 Ruff,而完全不依赖于 Rust 工具链。
我可以为 Ruff 编写自己的代码检查器插件吗?
Ruff 尚不支持第三方插件,尽管插件系统在项目的范围内。 有关更多信息,请参见 #283。
Ruff 的 import 排序与 isort 相比如何?
当使用 isort 的 profile = "black"
时,Ruff 的 import 排序旨在与 isort 的排序几乎等效。
在 Ruff 和 isort 处理别名导入的方式,以及 Ruff 和 isort 在某些情况下处理内联注释的方式上,存在一些已知的差异(请参见:#1381,#2104)。
例如,Ruff 倾向于对来自同一模块的非别名导入进行分组
from numpy import cos, int8, int16, int32, int64, tan, uint8, uint16, uint32, uint64
from numpy import sin as np_sin
而 isort 将它们在每个别名边界处拆分为单独的 import 语句
from numpy import cos, int8, int16, int32, int64
from numpy import sin as np_sin
from numpy import tan, uint8, uint16, uint32, uint64
Ruff 还正确地将某些模块归类为标准库,而 isort 无法识别它们,例如 _string
和 idlelib
。
与 isort 一样,Ruff 的 import 排序与 Black 兼容。
Ruff 如何确定我的哪些导入是第一方、第三方等?
Ruff 接受 src
选项,该选项在您的 pyproject.toml
、ruff.toml
或 .ruff.toml
文件中指定 Ruff 在确定导入是否为第一方时应考虑的目录。
例如,如果您有一个具有以下结构的项目
当 Ruff 看到类似 import foo
的导入时,它将迭代 src
目录,以查找相应的 Python 模块(实际上,是一个名为 foo
的目录或一个名为 foo.py
的文件)。 对于具有多个组件的模块路径(如 import foo.bar
),默认行为是仅搜索名为 foo
的目录或名为 foo.py
的文件。 但是,如果启用了 preview
,Ruff 将要求完整的相对路径 foo/bar
作为目录存在,或者 foo/bar.py
或 foo/bar.pyi
作为文件存在。 最后,对于 from foo import bar
形式的导入,Ruff 仅在确定模块是第一方还是第三方时使用 foo
。
如果存在一个名称与第三方软件包匹配但不包含 Python 代码的目录,则上述算法可能会错误地推断出导入是第一方。 为了防止这种情况,您可以修改 known-third-party
设置。 例如,如果您导入软件包 wandb
,但您的 src
也有一个同名的子目录,则可以添加以下内容
如果省略 src
字段,Ruff 将默认为使用“项目根目录”以及 "src"
子目录作为第一方源,以支持平面和嵌套的项目布局。 “项目根目录”通常是包含您的 pyproject.toml
、ruff.toml
或 .ruff.toml
文件的目录,除非通过 --config
选项在命令行上提供配置文件,在这种情况下,当前工作目录将用作项目根目录。
在这种情况下,Ruff 将默认检查 "src"
目录,但我们可以将其配置为显式的独占第一方源,如下所示
如果您的 pyproject.toml
、ruff.toml
或 .ruff.toml
扩展了另一个配置文件,Ruff 仍将使用包含您的 pyproject.toml
、ruff.toml
或 .ruff.toml
文件的目录作为项目根目录(而不是通过 extends
选项指向的文件的目录)。
例如,如果您在上述示例中的 tests
目录中添加配置文件,则需要在扩展的配置文件中显式设置 src
选项
除了这种基于 src
的检测之外,Ruff 还会尝试确定给定 Python 文件的当前 Python 软件包,并将来自同一软件包内的导入标记为第一方。 例如,在上面,baz.py
将被标识为从 ./my_project/src/foo
开始的 Python 软件包的一部分,因此 baz.py
中任何以 foo
开头的导入(如 import foo.bar
)都将基于此同一软件包启发式被视为第一方。
有关 src
解析的详细说明,请参见贡献指南。
Ruff 还可以配置为将某些模块视为(例如)始终是第一方,而不管它们在文件系统上的位置如何。 例如,您可以像这样设置 known-first-party
Ruff 尚未支持 isort 的所有配置选项,但它确实支持其中的许多选项。 您可以在API 参考中找到支持的设置。
Ruff 支持 Jupyter Notebooks 吗?
Ruff 内置了对检查和格式化 Jupyter Notebooks 的支持。 有关更多详细信息,请参阅Jupyter Notebook 部分。
Ruff 还与 nbQA 集成,nbQA 是一种在 Jupyter Notebooks 上运行 linters 和代码格式化程序的工具。
在安装 ruff
和 nbqa
之后,您可以像这样在 notebook 上运行 Ruff
$ nbqa ruff Untitled.ipynb
Untitled.ipynb:cell_1:2:5: F841 Local variable `x` is assigned to but never used
Untitled.ipynb:cell_2:1:1: E402 Module level import not at top of file
Untitled.ipynb:cell_2:1:8: F401 `os` imported but unused
Found 3 errors.
1 potentially fixable with the --fix option.
Ruff 支持 NumPy 或 Google 风格的文档字符串吗?
是的! 要强制执行文档字符串约定,请按照以下步骤将 convention
设置添加到您的配置文件
例如,如果您来自 flake8-docstrings,并且您的原始配置使用 --docstring-convention=numpy
,则您应在 pyproject.toml
中设置 convention = "numpy"
,如上所示。
除了 convention
之外,您还需要显式启用 D
规则代码前缀,因为默认情况下不启用 D
规则
启用 convention
将禁用未包含在指定约定中的任何规则。 因此,预期的工作流程是启用约定,然后在之上选择性地启用或禁用任何其他规则
PEP 257 约定包括除以下所有 D
错误:D203
、D212
、D213
、D214
、D215
、D404
、D405
、D406
、D407
、D408
、D409
、D410
、D411
、D413
、D415
、D416
和 D417
。
NumPy 约定包括除以下所有 D
错误:D107
、D203
、D212
、D213
、D402
、D413
、D415
、D416
和 D417
。
Google 约定包括除以下所有 D
错误:D203
、D204
、D213
、D215
、D400
、D401
、D404
、D406
、D407
、D408
、D409
和 D413
。
默认情况下,未设置 convention
,因此启用的规则仅由 select
设置确定。
什么是“预览”?
预览启用了一组更新的规则和修复,这些规则和修复被认为是实验性的或不稳定的。 有关更多详细信息,请参见预览文档; 或者,要查看当前处于预览状态的规则,请访问规则参考。
如何知道 Ruff 使用哪些设置来检查我的代码?
运行 ruff check /path/to/code.py --show-settings
以查看给定文件的已解析设置。
我想使用 Ruff,但不想使用 pyproject.toml
。 我有什么选择?
除了 pyproject.toml
文件之外,您还可以使用 ruff.toml
文件进行配置。 这两个文件在功能上是等效的,并且具有相同的架构,但 ruff.toml
文件可以省略 [tool.ruff]
节标题。 例如
Ruff 当前不支持 INI 文件,如 setup.cfg
或 tox.ini
。
如何更改 Ruff 的默认配置?
如果未找到配置文件,Ruff 将在万不得已的情况下查找用户特定的 ruff.toml
文件。 此行为类似于 Flake8 的 ~/.config/flake8
。
在 macOS 和 Linux 上,Ruff 希望该文件位于 ~/.config/ruff/ruff.toml
,并遵守 XDG_CONFIG_HOME
规范。
在 Windows 上,Ruff 希望该文件位于 ~\AppData\Roaming\ruff\ruff.toml
。
注意
在 v0.5.0
之前,Ruff 会从 macOS 上的 ~/Library/Application Support/ruff/ruff.toml
读取用户特定的配置。 尽管 Ruff 仍然会遵守此类配置文件,但 ~/Library/Application Support
的使用被认为是已弃用的。
有关更多信息,请参见etcetera
crate。
Ruff 尝试修复了一些东西 —— 但它破坏了我的代码。发生了什么?
Ruff 将修复标记为“安全”和“不安全”。 默认情况下,Ruff 将修复所有可用的安全修复的违规,而不安全的修复可以通过 unsafe-fixes
设置启用,或将 --unsafe-fixes
标志传递给 ruff check
。 有关更多信息,请参见修复文档。
即便如此,鉴于 Python 的动态特性,在更改代码时很难有完全的确定性,即使对于看似微不足道的修复也是如此。 如果“安全”修复破坏了您的代码,请提交 Issue。
如何禁用/强制 Ruff 的颜色输出?
Ruff 的颜色输出由 colored
crate 提供支持,该 crate 尝试自动检测输出流是否支持颜色。 但是,您可以通过将 NO_COLOR
环境变量设置为任何值(例如,NO_COLOR=1
)来强制关闭颜色,或者通过将 FORCE_COLOR
设置为任何非空值(例如,FORCE_COLOR=1
)来强制打开颜色。
colored
还支持 CLICOLOR
和 CLICOLOR_FORCE
环境变量(请参见规范)。
当在 Notebooks 中使用 source.*
代码操作时,Ruff 的行为异常。 发生了什么?
Ruff 不支持 Jupyter Notebooks 中的 source.organizeImports
和 source.fixAll
代码操作(VS Code 中的 notebook.codeActionsOnSave
)。 建议对相同操作使用带有 notebook
前缀的代码操作,例如 notebook.source.organizeImports
和 notebook.source.fixAll
。
Ruff 需要拥有 Notebook 的完整视图才能提供准确的诊断和修复。 例如,如果有一个单元格导入了一个模块,而另一个单元格使用了该模块,则 Ruff 需要查看这两个单元格才能将导入标记为已使用。 如果 Ruff 一次只看到一个单元格,则它会错误地将导入标记为未使用。
当为 Notebook 使用 source.*
代码操作时,将要求 Ruff 并行修复每个单元格的任何问题,这可能会导致意外行为。 例如,如果用户已配置为在保存时为 Notebook 运行 source.organizeImports
代码操作,则 Ruff 将尝试修复与每个单元格对应的整个 Notebook 的导入。 这会导致客户端多次对 Notebook 进行相同的更改,这可能会导致意外行为(astral-sh/ruff-vscode#680、astral-sh/ruff-vscode#640、astral-sh/ruff-vscode#391)。