Ruff Python 代码检查与格式化
一句话概述:Ruff 是用 Rust 写的 Python 代码检查器和格式化器,比 Flake8 快 100 倍,一个工具替代 Flake8 + Black + isort + pyupgrade 等十几个工具,零依赖单文件。
核心知识点
| 概念 | 白话解释 |
|---|
| Linter(检查器) | 扫描代码找问题:Bug、风格、安全漏洞 |
| Formatter(格式化器) | 统一代码格式:缩进、换行、引号风格 |
| 900+ 条规则 | 内置 Flake8、isort、pyupgrade 等几十个工具的规则 |
| Rust 实现 | 用 Rust 写的,极快,大项目也是毫秒级 |
| 零依赖 | 不需要 Python 运行时,装一个二进制就行 |
| pyproject.toml | 推荐的配置方式,所有 Ruff 设置写在一个文件里 |
安装配置
# 方式一:pip(最常用)
pip install ruff # 安装 Ruff
# 方式二:pipx(全局隔离安装)
pipx install ruff
# 方式三:uv(最快)
uv tool install ruff
# 方式四:Homebrew
brew install ruff
# 方式五:conda
conda install -c conda-forge ruff
# 检查版本
ruff --version # 查看安装的版本(当前最新 v0.15.x)
配置文件
# pyproject.toml - 推荐的配置方式
[tool.ruff]
target-version = "py311" # 目标 Python 版本
line-length = 88 # 每行最大长度(和 Black 一致)
indent-width = 4 # 缩进宽度
fix = true # 默认自动修复
# 排除目录
exclude = [
".venv",
"migrations",
"__pycache__",
"*.egg-info",
]
[tool.ruff.lint]
# 启用的规则集
select = [
"E", # pycodestyle 错误
"W", # pycodestyle 警告
"F", # Pyflakes
"I", # isort(导入排序)
"N", # pep8-naming(命名规范)
"UP", # pyupgrade(现代化语法)
"B", # flake8-bugbear(常见 Bug)
"S", # flake8-bandit(安全检查)
"C4", # flake8-comprehensions(推导式优化)
"SIM", # flake8-simplify(代码简化)
"RUF", # Ruff 自己的规则
]
# 忽略的规则
ignore = [
"E501", # 行太长(用格式化器处理)
"S101", # assert 使用(测试里需要用)
]
# 每个文件的规则覆盖
[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = ["S101", "S106"] # 测试文件忽略安全检查
"__init__.py" = ["F401"] # __init__.py 忽略未使用导入
[tool.ruff.lint.isort]
known-first-party = ["myproject"] # 第一方库(你自己的包)
[tool.ruff.format]
quote-style = "double" # 双引号
indent-style = "space" # 空格缩进
skip-magic-trailing-comma = false # 保留尾逗号
line-ending = "auto" # 自动检测换行符
基本使用
代码检查(Lint)
# 检查代码
ruff check . # 检查当前目录所有 Python 文件
ruff check src/ # 检查指定目录
ruff check script.py # 检查指定文件
# 自动修复
ruff check . --fix # 自动修复可修复的问题
ruff check . --fix --unsafe-fixes # 包括不安全的修复(需人工确认)
# 查看详情
ruff check . --show-fixes # 显示每个问题的修复建议
ruff check . --statistics # 显示统计信息
# 格式化代码
ruff format . # 格式化当前目录
ruff format src/ # 格式化指定目录
# 检查格式(不修改,只报告)
ruff format . --check # CI 中用,有不规范的就报错
ruff format . --diff # 显示会做的修改(不实际修改)
示例:Ruff 能发现什么
# 修复前 ❌
import os # F401: 未使用的导入
import json
from typing import List, Dict # UP006: 用 list/dict 替代 typing.List/Dict
def processData(data): # N802: 函数名应该用小写加下划线
result = []
for item in data:
if item != None: # E711: 应该用 is not None
x = item["value"]
if x == True: # E712: 应该用 is True
result.append(x)
return result
names = list() # C408: 直接用 [] 代替 list()
# 修复后 ✅(ruff check --fix)
import json
def process_data(data):
result = []
for item in data:
if item is not None:
x = item["value"]
if x is True:
result.append(x)
return result
names = []
高级用法
导入排序(替代 isort)
# 修复前 ❌ 导入混乱
import json
from myproject.utils import helper
import os
from pathlib import Path
import requests
from myproject.models import User
# 修复后 ✅ ruff 自动排序
import json # 1. 标准库
import os
from pathlib import Path
import requests # 2. 第三方库
from myproject.models import User # 3. 本项目
from myproject.utils import helper
Pre-commit 集成
# .pre-commit-config.yaml
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.0 # 使用最新版本
hooks:
- id: ruff # 代码检查
args: [--fix] # 自动修复
- id: ruff-format # 代码格式化
pip install pre-commit # 安装 pre-commit
pre-commit install # 安装到 git hooks
# 每次 git commit 都会自动检查和格式化
VS Code 集成
// .vscode/settings.json
{
"[python]": {
"editor.formatOnSave": true, // 保存时格式化
"editor.defaultFormatter": "charliermarsh.ruff", // 用 Ruff 格式化
"editor.codeActionsOnSave": {
"source.fixAll.ruff": "explicit", // 保存时自动修复
"source.organizeImports.ruff": "explicit" // 保存时排序导入
}
}
}
块级禁用规则(v0.15 新功能)
# ruff: disable[N803] # 从这里开始禁用 N803 规则
def MyFunction(A, B): # 不会报命名警告
return A + B
# ruff: enable[N803] # 恢复启用
# noqa 行级禁用
x = 1 # noqa: F841 # 这一行忽略 F841 规则
CI/CD 集成
# .github/workflows/lint.yml
name: Lint
on: [push, pull_request]
jobs:
ruff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/ruff-action@v3 # 官方 GitHub Action
with:
args: "check" # 检查代码
- uses: astral-sh/ruff-action@v3
with:
args: "format --check" # 检查格式
常见报错
| 报错信息 | 原因 | 解决方案 |
|---|
F401 imported but unused | 导入了但没用 | 删掉没用的 import,或在 __init__.py 加 # noqa |
E501 line too long | 行太长 | 用 ruff format 自动换行 |
I001 import block not sorted | 导入没排序 | ruff check --fix 自动排序 |
UP006 use list instead of List | 旧式类型注解 | ruff check --fix 自动升级 |
| 和 Black 格式不同 | 配置差异 | Ruff 默认兼容 Black,检查 line-length 设置 |
| 规则太多太烦 | 选了太多规则 | 从 ["E", "F", "I"] 开始,逐步添加 |
速查表
# CLI 命令
ruff check . # 检查代码
ruff check . --fix # 检查并修复
ruff format . # 格式化代码
ruff format . --check # 检查格式(不修改)
ruff format . --diff # 显示差异
ruff rule E501 # 查看某条规则的说明
ruff linter # 列出所有可用的 linter
ruff version # 查看版本
# 常用规则集代码
E/W # pycodestyle(PEP8 风格)
F # Pyflakes(逻辑错误)
I # isort(导入排序)
N # pep8-naming(命名规范)
UP # pyupgrade(语法现代化)
B # flake8-bugbear(常见 Bug)
S # flake8-bandit(安全)
C4 # flake8-comprehensions(推导式)
SIM # flake8-simplify(简化)
RUF # Ruff 自有规则
# 行内控制
# noqa # 忽略本行所有规则
# noqa: F401 # 忽略本行特定规则
# ruff: noqa # 忽略整个文件
# type: ignore # 忽略类型检查(mypy)
参考:Ruff 官网 | GitHub | 规则列表