现代 Python 开发的“黄金搭档”
编辑我们来重点介绍一下 Ruff
+ pre-commit
这个堪称现代 Python 开发的“黄金搭档”。
这个组合的核心思想是:将代码规范化和质量检查完全自动化,并集成到你的 Git 工作流中,从而在代码被提交之前就确保其质量和风格的一致性。
第一部分:理解两位主角
1. Ruff
:身兼数职的瑞士军刀 swiss-army-knife
我们已经知道 Ruff
是一个极速的代码检查(Linter)和格式化(Formatter)工具。在与 pre-commit
结合时,它的优势被发挥得淋漓尽致:
Linter 角色:它会检查你的代码是否存在潜在的 bug(如未使用的变量)、不规范的写法(违反 PEP 8)、以及可以改进的模式。它取代了
Flake8
、Pylint
等传统工具。Formatter 角色:它会统一代码的格式,处理空格、换行、引号等风格问题。它旨在成为
Black
的一个更快、配置更集成的替代品。Import Sorter 角色:它内置了对
import
语句的排序功能,完美取代了isort
。Auto-fixer 角色:最强大的是,
Ruff
能自动修复它发现的绝大多数问题,无论是格式错误还是代码规范问题。
关键优势:快。因为它快,所以在每次提交代码时运行它,几乎感觉不到延迟,不会打断开发者的心流。
2. pre-commit
:尽职尽责的代码仓库门卫 guard
pre-commit
是一个 Git 钩子(hook)管理框架。所谓“钩子”,就是在 Git 执行特定操作(如 commit
、push
)之前或之后自动触发的脚本。
pre-commit
让你能够轻松地管理这些钩子。它的工作流程是:
你在项目中配置一个
.pre-commit-config.yaml
文件,定义好要运行哪些检查工具(比如Ruff
)。当你运行
git commit
时,pre-commit
会拦截这次提交。它会针对你即将提交的文件(staged files)运行你定义好的工具。
如果工具检查不通过:
如果工具(如
Ruff
)能自动修复,它会直接修改你的文件。然后pre-commit
会中止本次提交,并提示你检查修改。你只需再次git add
被修改的文件,然后重新commit
即可。如果发现无法自动修复的严重问题,它会直接报错并中止提交,直到你手动修复问题。
如果所有工具检查都通过,你的
commit
才会成功创建。
关键优势:自动化和强制性。它确保了没有任何不符合规范的代码能“溜进”你的代码历史记录中,对团队协作尤其重要。
第二部分:实战:如何配置 Ruff
+ pre-commit
假设你已经有一个 Git 项目,我们来一步步完成配置。
第 1 步:安装工具
在你的项目虚拟环境中安装 Ruff
和 pre-commit
。
# 激活你的虚拟环境
# source .venv/bin/activate
pip install ruff pre-commit
第 2 步:配置 Ruff
Ruff
的配置通常写在项目根目录的 pyproject.toml
文件中(这是现代 Python 项目推荐的做法),或者一个独立的 ruff.toml
文件。
在你的 pyproject.toml
文件中添加以下配置:
# pyproject.toml
[tool.ruff]
# 设置代码行的最大长度,与 black 默认值保持一致
line-length = 88
# 允许 Ruff 自动修复所有安全的问题
fix = true
[tool.ruff.lint]
# 选择要启用的规则集。这组规则非常常用:
# E, F: 来自 Flake8 的核心规则 (pycodestyle, Pyflakes)
# I: import 排序 (来自 isort)
# UP: pyupgrade, 自动将代码升级到新语法
# B: flake8-bugbear, 发现潜在的逻辑错误
select = ["E", "F", "I", "UP", "B"]
# 如果有需要,可以忽略特定的规则
# ignore = ["E501"] # 例如,如果不想限制行长度
[tool.ruff.format]
# 使用双引号,而不是单引号
quote-style = "double"
提示:
Ruff
的规则非常多,你可以从一个基础的配置开始,然后根据团队的需求逐步增减。select = ["E", "F", "I"]
是一个很好的起点。
第 3 步:配置 pre-commit
在你的项目根目录创建一个名为 .pre-commit-config.yaml
的文件,并写入以下内容:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# 确保使用一个固定的版本号,以保证团队成员之间的一致性
rev: v0.4.8 # 你可以在 Ruff 官网或 GitHub 找到最新版本号
hooks:
# 第一个钩子:使用 Ruff 作为 Linter (代码检查)
- id: ruff
# --fix 参数让它在运行时自动修复问题
# --exit-non-zero-on-fix 表示如果进行了修复,也算作失败,从而中止提交
args: [--fix, --exit-non-zero-on-fix]
# 第二个钩子:使用 Ruff 作为 Formatter (代码格式化)
- id: ruff-format
第 4 步:激活 pre-commit
钩子
在你的项目根目录(与 .git
目录同级)运行以下命令:
pre-commit install
这个命令会将 .pre-commit-config.yaml
中定义的钩子安装到你的本地 Git 仓库的 .git/hooks
目录中。每个克隆了该仓库的开发者都需要运行一次此命令来激活钩子。
第三部分:见证奇迹的时刻 (工作流演示)
现在,你已经配置完毕。让我们看看它在实际工作中是如何运作的:
你写了一段不那么规范的代码,比如:
# my_script.py import os, sys # 同行导入,不规范 def my_func( name): # 参数前后缺少空格 unused_variable = 1 # 未使用的变量 print("hello " + name) # 使用 + 拼接字符串,可以更优
你将这个文件添加到暂存区并尝试提交:
git add my_script.py git commit -m "Add a new feature"
pre-commit
会立即启动,并运行Ruff
:(base) ➜ my-project git commit -m "Add a new feature" Ruff: linter.............................................................Failed - hook id: ruff - files were modified by this hook Found 4 errors (4 fixable). - my_script.py:1:10: I001 [*] Import statements are not sorted - my_script.py:3:15: E231 Missing whitespace after ',' - my_script.py:4:5: F841 [*] Local variable `unused_variable` is assigned to but never used - my_script.py:5:5: B034 [*] `print("hello " + name)` can be rewritten as a f-string [*] Found 4 fixable violations. Ruff: formatter..........................................................Failed - hook id: ruff-format - files were modified by this hook 1 file reformatted
提交被中止了!
pre-commit
告诉你自己动手修改了文件。现在你查看my_script.py
,会发现它已经被Ruff
自动修复和格式化了:# my_script.py (自动修复后) import os import sys def my_func(name): # 注意:像 "unused_variable" 这样的逻辑问题,Ruff 默认不会自动删除, # 它会警告你,需要你手动处理。但格式和导入问题已经修复。 unused_variable = 1 print(f"hello {name}")
注意:对于 "unused variable",Ruff 的
--fix
通常会移除它,这里为了演示保留。但关键是,它会指出问题。你看到代码已经被修正,于是你接纳这些修改,然后再次提交:
# 再次添加被自动修改的文件 git add my_script.py # 再次提交 git commit -m "Add a new feature"
这一次,
pre-commit
再次运行Ruff
,发现所有问题都已解决,代码完全符合规范。(base) ➜ my-project git commit -m "Add a new feature" Ruff: linter.............................................................Passed Ruff: formatter..........................................................Passed [main a1b2c3d] Add a new feature 1 file changed, 5 insertions(+), 5 deletions(-)
提交成功!
总结
Ruff
+ pre-commit
的组合,为你和你的团队提供了一个强大、快速、自动化的代码质量保障体系。
对个人开发者:它强迫你养成良好的编码习惯,保持代码库的整洁。
对团队:它解决了代码风格不一的“圣战”,统一了规范,降低了 Code Review 中因风格问题产生的沟通成本,让大家更专注于业务逻辑本身。
这套流程一旦建立,就会成为项目开发中一个默默无闻但不可或缺的守护者。强烈建议在所有新的 Python 项目中都采用它。
来源
- 0
- 0
-
分享