Skip to content

使用 ruff 提升 Python 代码质量

ruff 介绍

Ruff 是一个 Python linter + formatter 工具。可以用来检测 Python 语法问题与格式化 Python 代码。

想要全面了解 Ruff,需要具体知晓, 它能够做到哪些事、取代哪些工具。

什么是 Linter

Linter 是一种代码检查工具,可以帮助我们改进代码:包括检查代码中的语法错误、编码风格问题和潜在的漏洞,并提供建议和修正方法。通过使用 Linter 工具,开发者可以快速地发现并修正程序中的错误,提高代码的质量。

Python 常见的 Linter 工具包括 Flake8, Pylint 等等。

什么是 Formatter

Code Formatter(代码格式化工具)是一种自动将源代码按照特定风格规范进行排版、缩进、换行、空格处理等操作的工具。它的目标是让代码风格统一,提高可读性,并减少团队协作中因风格差异带来的争议。

Python 常见的 Formatter 工具包括 Black, YAPF 等等。

安裝使用

对于没有安装 Ruff 的人,请运行以下命令:

shell
pip install ruff

要在 Python 文件中使用格式化程序功能,可以运行 ruff format /path/to/file.py 命令,它将格式化该文件。

要格式化目录中的所有文件,可以运行 ruff format . 命令。

linter

1、要将 Ruff 作为 linter 运行,请尝试以下任一操作:

ruff check .                        # 检查当前目录(以及任何子目录)中的所有文件
ruff check path/to/code/            # 对 `/path/to/code`(及任何子目录)中的所有文件进行检查
ruff check path/to/code/*.py        # 检查 `/path/to/code` 中的所有 `.py` 文件
ruff check path/to/code/to/file.py  # 检查 `file.py`
ruff check @arguments.txt           # 使用输入文件 Lint,将其内容视为以新行分隔的命令行参数。

2、或者,将 Ruff 作为格式化程序运行:

ruff format .                        # 格式化当前目录(及任何子目录)中的所有文件
ruff format path/to/code/            # 格式化 `/path/to/code`(及任何子目录)中的所有文件
ruff format path/to/code/*.py        # 格式化 `/path/to/code` 中的所有 `.py` 文件
ruff format path/to/code/to/file.py  # 格式化 `file.py`.
ruff format @arguments.txt           # 使用输入文件格式,将其内容视为以新行分隔的命令行参数。

例子

如果有一个这样的代码:

python
log = new_log(tracker["ip_address"], tracker["request_url"], tracker["request_port"],
              tracker["request_path"], tracker["request_method"],
              tracker["browser_type"], tracker["operating_system"], tracker["request_time"])

运行指令检测语法问题

shell
$ ruff check main.py
main.py:1:7: F821 Undefined name `new_log`
main.py:1:15: F821 Undefined name `tracker`
main.py:1:38: F821 Undefined name `tracker`
main.py:1:62: F821 Undefined name `tracker`
main.py:2:15: F821 Undefined name `tracker`
main.py:2:40: F821 Undefined name `tracker`
main.py:3:15: F821 Undefined name `tracker`
main.py:3:40: F821 Undefined name `tracker`
main.py:3:69: F821 Undefined name `tracker`
Found 9 errors.

format

运行检查 ruff format main.py 之后如下图:

python
log = new_log(
    tracker["ip_address"],
    tracker["request_url"],
    tracker["request_port"],
    tracker["request_path"],
    tracker["request_method"],
    tracker["browser_type"],
    tracker["operating_system"],
    tracker["request_time"],
)

自动修复错误 (autofix)

Linter 扫描到问题之后,最好是能够自动修复错误,不仅省时也相当省力,Ruff 也支持 autofix 的功能,只要加上 参数就 --fix 能够启用自动修复

shell
$ ruff check --fix test.py

配置规则

Ruff 总共支持三种设定文件:pyproject.tomlruff.toml.ruff.toml

如果不知道怎么开始,参考文件是最快上手的方式。 以下的范例与解说,我采用设定文件格式是 pyproject.toml

Ruff 因为功能众多,设定上较为复杂。所幸, 大部分时候,我们只需要设定一些基本的项目

基本设定

pyproject.toml 中,设置的 key 定是 [tool.xxx] 格式。

Linter 部分,一些基本的设定比如 line-length 和 Flake8 类似。其中 select 和没有列出的 ignore 相对重要。

Ruff 默认只会显示 EF 系列的错误讯息(而 Flake8 还有 W 系列)。 想要增加或排除特定部分的错误讯息警示,就得透过 select 字段调整。比如:

toml
[tool.ruff]
line-length = 100
target-version = "py310"

[tool.ruff.lint]
select = ["E", "F", "I", "UP"]  # I 和 UP 是 isort 和 pyupgrade

[tool.ruff.format]
# 选项有 "single" 和 "double"
quote-style = "single"
# 启用 docstring 代码片段格式化
docstring-code-format = true

select 加上了 IUP。分别代表了 isort 和 pyupgrade。一旦开启了它们,Ruff 就会提示相关错误,并在有错误时自动修正。 (autofix 默认为打开)

因为开启了 UP,所以必须设定 target-version(这里为 py310),意味着 Ruff 会将代码中旧的写法自动转换(autofix)为 Python 3.10 的写法。

pre-commit 设定

pre-commit 设定相对单纯,更细部的行为,hook 会自动读取配置文件中的内容。

- repo: https://github.com/astral-sh/ruff-pre-commit
  rev: v0.1.4
  hooks:
    - id: ruff
      args:
        - --fix
    - id: ruff-format

参考

https://docs.astral.sh/ruff/formatter/

https://blog.kyomind.tw/ruff/

https://blog.davidz.cn/post/aio-ruff