核心目标:全面掌握 Ruff 的安装配置、规则体系、自动修复、IDE 集成和生产级 CI/CD 工作流,实现 Python 代码质量检查从"跑完喝杯咖啡"到"瞬间完成"的升级。

前置知识:Python 3.8+ 基础、了解 pip / pyproject.toml,了解 Flake8 / Black / isort 等传统工具更佳。


1.1 什么是 Ruff

Ruff 是一个用 Rust 编写的极速 Python linter 和 formatter,由 Astral 团队开发。它在单个工具中整合了 Flake8、isort、pyupgrade、pylint、pydocstyle 等数十个工具的功能。

整合

🦀 Ruff (一个工具搞定)

Linter
700+ 规则

Formatter
Black 兼容

Import 排序
isort 兼容

Auto-fix
安全自动修复

传统工具链 (多个独立工具)

Flake8
pyflakes + pycodestyle

isort
import 排序

Black
代码格式化

pyupgrade
语法现代化

pylint
深度检查

pydocstyle
文档检查

1.1.1 速度对比——为什么用 Ruff

工具 Lint 10 万行 Lint 100 万行 底层语言
Ruff 0.05s 0.3s Rust
Flake8 3s 35s Python
Pylint 12s 140s Python
Black 2.5s 28s Python
# 同一个项目的实际测试:
# cpython 源码 (~200 万行 Python)
$ time ruff check .        # 0.3s real
$ time flake8 .             # 53s  real  ← Ruff 快 170 倍!
$ time pylint *.py          # 3min+      ← Ruff 快 600 倍!

Ruff 快到什么程度?你保存文件后还没松开手,lint 结果已经出来了。


1.2 安装与第一个命令

1.2.1 安装方式

# 推荐: pip 安装
pip install ruff

# 或使用 pipx (全局隔离)
pipx install ruff

# 验证安装
ruff --version
# ruff 0.6.x

1.2.2 第一个 lint 命令

# bad_code.py —— 一个有问题的文件
import os, sys, json            # ❌ 多模块一行
import collections              # ❌ 未使用的 import

unused_var = "hello"            # ❌ 未使用的变量

def my_function( x,y ):        # ❌ 括号内多余空格
    result=x+y                  # ❌ 操作符两边缺空格
    return result

print(my_function(1,2))        # ❌ 逗号后缺空格
# 直接运行 ruff check
ruff check bad_code.py

Ruff 输出

bad_code.py:1:1: F401 [*] `collections` imported but unused
bad_code.py:1:10: F401 [*] `os` imported but unused
bad_code.py:1:14: F401 [*] `sys` imported but unused
bad_code.py:1:19: F401 [*] `json` imported but unused
bad_code.py:3:1: F841 [*] Local variable `unused_var` is assigned to but never used
bad_code.py:5:17: E201 Whitespace after '('
bad_code.py:5:19: E231 Missing whitespace after ','
bad_code.py:5:21: E202 Whitespace before ')'
bad_code.py:6:10: E225 Missing whitespace around operator
Found 9 errors.
[*] 9 fixable with the `--fix` option.

1.2.3 自动修复

# 一键修复所有可自动修复的问题
ruff check --fix bad_code.py

# 修复后的代码:
import collections              # 只移除了未使用的
# os, sys, json 已被删除

def my_function(x, y):          # ✅ 空格正确
    result = x + y              # ✅ 操作符空格正确
    return result

print(my_function(1, 2))        # ✅ 逗号后空格正确
# unused_var 被删除

2.1 Linter——700+ 规则体系

2.1.1 规则分类

Ruff 的规则按前缀分类,每个前缀对应一个工具或检查领域:

Ruff 规则体系 (700+)

F: Pyflakes

未使用的 import

未使用的变量

重复定义

E/W: pycodestyle

行太长

行尾空格

I: isort

import 顺序错误

D: pydocstyle

缺少模块文档

首句命令式

UP: pyupgrade

用 list 替代 typing.List

用 dict[] 替代 typing.Dict[]

B: flake8-bugbear

可变默认参数

raise 链保留

更多...

简化 (flake8-simplify)

类型检查导入

Pylint 规则

Ruff 专有规则

2.1.2 常用规则速查表

规则 序号 级别 说明 可修复
F401 Error 未使用的 import
F841 Error 未使用的变量
E501 79 Error 行过长
E711 Error == None 应用 is None
I001 Error import 未排序
UP006 Error 使用旧式 typing.List
B006 Error 可变默认参数
B904 Error raise 未保留异常链
SIM108 Error 可用三元表达式简化
SIM201 Error not a in ba not in b
D100 Error 缺少模块级 docstring
TCH001 Error 类型检查专用 import 应移入 TYPE_CHECKING
RUF100 Warn # noqa 注释指向不存在的规则

2.1.3 查看所有可用规则

# 列出所有规则
ruff rule --all

# 按前缀过滤
ruff rule --all | grep "^F"     # Pyflakes 规则
ruff rule --all | grep "^UP"    # pyupgrade 规则

# 查看某条规则的详情
ruff rule F401
# 输出: 规则描述、示例、出处、自动修复能力

2.2 配置——pyproject.toml 一站搞定

2.2.1 完整配置模板

# pyproject.toml
[tool.ruff]

# ── 目标 Python 版本 ──
target-version = "py311"       # 3.11 语法特性

# ── 行宽 ──
line-length = 100              # 超长警告阈值

# ── 排除目录 ──
exclude = [
    ".git",
    ".venv",
    "__pycache__",
    "build",
    "dist",
    "migrations",              # Django migrations
]

# ── Linting 规则选择 ──
[tool.ruff.lint]
select = [
    # Pyflakes (基础错误)
    "F",
    # pycodestyle (代码风格)
    "E", "W",
    # isort (import 排序)
    "I",
    # pyupgrade (语法现代化)
    "UP",
    # flake8-bugbear (常见 bug)
    "B",
    # flake8-simplify (简化建议)
    "SIM",
    # 类型检查 import
    "TCH",
    # Pylint 规则 (部分)
    "PL",
    # Ruff 专有规则
    "RUF",
]

ignore = [
    # 允许行尾空白 (比如 Markdown 的换行)
    "W291",
    # 不强制文档字符串
    "D100", "D104",
]

# 修正特定规则配置
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]          # __init__.py 允许未使用 import
"tests/**/*.py" = ["PLR2004"]     # 测试文件中允许魔数
"scripts/*.py" = ["T201"]         # 脚本中允许 print

[tool.ruff.lint.isort]
known-first-party = ["myproject"] # 第一方包前缀
force-single-line = true          # 强制单行导入

[tool.ruff.lint.pylint]
max-args = 6                      # 最大函数参数数

# ── Formatter 配置 ──
[tool.ruff.format]
quote-style = "double"            # 双引号 (Black 默认)
indent-style = "space"            # 空格缩进
skip-magic-trailing-comma = false # 保留尾随逗号魔法
docstring-code-format = true      # 格式化 docstring 中的代码示例

2.2.2 按场景选择规则集

# ── 场景 1: 最小规则 (宽松, 只抓硬伤) ──
[tool.ruff.lint]
select = ["F", "E", "B"]          # Pyflakes + pycodestyle + bugbear

# ── 场景 2: 推荐规则 (日常开发) ──
[tool.ruff.lint]
select = ["F", "E", "W", "I", "UP", "B", "SIM", "TCH", "RUF"]

# ── 场景 3: 严格规则 (开源项目/团队规范) ──
[tool.ruff.lint]
select = [
    "F", "E", "W", "I", "D",         # + pydocstyle
    "UP", "B", "SIM", "TCH", "PL",   # + Pylint 子集
    "C4", "RUF", "T20", "PT"         # + 其他
]

2.2.3 配置优先级

最高优先级

项目级

项目级 (备选)

最低优先级

覆盖

覆盖

CLI 参数
ruff check --select F401

最终配置

pyproject.toml
[tool.ruff]

ruff.toml
或 .ruff.toml

Ruff 内置默认值


2.3 Formatter——Black 兼容的格式化器

2.3.1 基本使用

# 格式化当前目录
ruff format .

# 检查格式化差异 (不修改文件)
ruff format --check .

# 仅格式化指定文件
ruff format src/ tests/

# 显示差异 (类似 git diff)
ruff format --diff .

2.3.2 Ruff Formatter vs Black

# ── 原始代码 ──
def process_data(items: list[int], config: dict[str, any] = None) -> dict[str, list[int]]:
    result = {}
    for item in items:
        if item > 0 and item % 2 == 0 and config and isinstance(config.get('mode'), str):
            result.setdefault(config['mode'], []).append(item * 2 + 1)
    return result

# ── Black 格式化 (line-length=88) ──
def process_data(
    items: list[int], config: dict[str, any] = None
) -> dict[str, list[int]]:
    result = {}
    for item in items:
        if (
            item > 0
            and item % 2 == 0
            and config
            and isinstance(config.get("mode"), str)
        ):
            result.setdefault(config["mode"], []).append(item * 2 + 1)
    return result

# ── Ruff format (line-length=88) ── 99.9% 相同!
# 差异仅在极端边缘情况下,Ruff 有意保持与 Black 高度兼容
特性 Black Ruff Formatter
格式化质量 ✅ 成熟 ✅ 兼容 Black
速度 2.5s (10万行) 0.03s (80x)
配置项 极少 (哲学) 同样极少
--check / --diff
Jupyter Notebook
预览样式 ✅ (--preview) ✅ (--preview)

Ruff formatter 默认兼容 Black 99.9% 的输出。如果发现不一致,请提交 issue,Ruff 团队视之为 bug。


3.1 VS Code 集成——实时反馈

3.1.1 安装扩展

# 1. 安装 Ruff VS Code 扩展
#    在 VS Code 扩展市场搜索 "Ruff" (作者: Astral Software)
#    或命令行:
code --install-extension charliermarsh.ruff

3.1.2 settings.json 配置

{
    // ── 关闭其他 linter, 只用 Ruff ──
    "python.linting.enabled": false,
    "python.linting.flake8Enabled": false,
    "python.linting.pylintEnabled": false,

    // ── Ruff 配置 ──
    "[python]": {
        "editor.defaultFormatter": "charliermarsh.ruff",
        "editor.formatOnSave": true,                    // 保存时自动格式化
        "editor.codeActionsOnSave": {
            "source.fixAll.ruff": "explicit",           // 保存时自动修复
            "source.organizeImports.ruff": "explicit"   // 保存时整理 import
        }
    },
    "ruff.enable": true,
    "ruff.lint.enable": true,
    "ruff.format.enable": true,

    // 可选: 将格式化方式存入 import
    // 其他选项: "ruff.lineWidth": 100
}

3.1.3 工作流效果

Ctrl+S 保存文件

Ruff Lint
实时诊断

Ruff Fix
自动修复

Ruff Format
格式化代码

Ruff 整理
import 排序

编辑器内显示
波浪线 + 快速修复

代码自动清理

格式统一

import 有序


3.2 Pre-commit 集成——提交前自动检查

3.2.1 配置

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.6.0                    # 使用最新版本
    hooks:
      # Linter: 检查并修复
      - id: ruff
        args: [--fix, --exit-non-zero-on-fix]
        types_or: [python, pyi]

      # Formatter: 格式化
      - id: ruff-format
        types_or: [python, pyi, jupyter]
# 安装 pre-commit hooks
pip install pre-commit
pre-commit install

# 手动对所有文件运行
pre-commit run --all-files

# 之后每次 git commit 会自动触发:
# > ruff.....................................................................Passed
# > ruff-format............................................................Passed

3.2.2 进阶:仅在变更文件上运行

# .pre-commit-config.yaml (高性能版)
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.6.0
    hooks:
      - id: ruff
        args: [--fix]
        # 不传文件参数,ruff 自动处理暂存区文件

      - id: ruff-format

4.1 CI/CD 集成——门禁检查

4.1.1 GitHub Actions

# .github/workflows/lint.yml
name: Lint

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  ruff:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.11"

      - name: Install Ruff
        run: pip install ruff

      - name: Lint (不修复, 只检查)
        run: ruff check --output-format=github .

      - name: Format check (检查格式差异)
        run: ruff format --check --diff .
        # --output-format=github 使结果以 GitHub Annotation 显示

4.1.2 GitLab CI

# .gitlab-ci.yml
ruff:
  image: python:3.11
  script:
    - pip install ruff
    - ruff check --output-format=gitlab .
    - ruff format --check --diff .
  only:
    - merge_requests
    - main

4.1.3 仅检查变更文件——加速 CI

# 在 CI 中仅 lint 变更的文件 (相比 PR base)
git diff --name-only --diff-filter=ACMR origin/main...HEAD \
  -- '*.py' '*.pyi' \
  | xargs ruff check

4.2 迁移指南——从传统工具到 Ruff

4.2.1 从 Flake8 迁移

# Step 1: 生成 Ruff 配置 (读取现有 .flake8 配置)
ruff config

# Step 2: 对比 Ruff 和 Flake8 的检查结果
ruff check . > ruff-report.txt
flake8 . > flake8-report.txt
diff ruff-report.txt flake8-report.txt

# Step 3: 移除 Flake8 及其插件
pip uninstall flake8 flake8-bugbear flake8-simplify \
    flake8-comprehensions flake8-print pep8-naming

# Step 4: 安装 Ruff
pip install ruff

# Step 5: 更新 pyproject.toml

4.2.2 规则映射表

Flake8 插件 Ruff 前缀 覆盖率
pyflakes F 100%
pycodestyle E, W 99%
flake8-bugbear B 95%
flake8-simplify SIM 99%
flake8-comprehensions C4 99%
flake8-print T20 100%
pep8-naming N 97%
flake8-annotations ANN 90%
flake8-docstrings D 90%
flake8-pytest-style PT 98%
pylint PL(部分) ~60%

4.2.3 从 isort + Black 迁移

# 移除旧工具
pip uninstall black isort

# Ruff format 替代 Black
# 之前: black --check --diff .
# 之后: ruff format --check --diff .

# Ruff lint 替代 isort
# 之前: isort --check-only --diff .
# 之后: ruff check --select I --diff .

4.2.4 pyproject.toml 迁移对照

# ── 旧配置 ──
[tool.black]
line-length = 100
target-version = ["py311"]

[tool.isort]
profile = "black"
line_length = 100
known_first_party = ["myproject"]

[tool.flake8]
max-line-length = 100
extend-ignore = ["E203"]
# ── 新配置 (Ruff) ──
[tool.ruff]
line-length = 100
target-version = "py311"

[tool.ruff.lint.isort]
known-first-party = ["myproject"]

5.1 进阶技巧

5.1.1 忽略特定行

# 忽略单行
import unused_module  # noqa: F401

# 忽略特定规则
x = "very long string that exceeds the line length limit..."  # noqa: E501

# 忽略整段代码
# ruff: noqa: F841, E501
def experimental():
    x = 1  # 不会报告 F841
    y = very_long_function_name(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)  # 不会报告 E501
# ruff: noqa: F841, E501

5.1.2 仅对特定文件启用/禁用规则

[tool.ruff.lint.per-file-ignores]
# CLI 脚本中允许 print
"cli.py" = ["T201"]
"manage.py" = ["T201"]

# 测试文件更宽松
"tests/**/*.py" = [
    "PLR2004",  # 魔数
    "S101",     # assert (测试中正常)
    "ARG001",   # 未使用函数参数 (fixture 中用)
]

# Django migrations 不使用 lint
"**/migrations/*.py" = ["ALL"]

# Notebook 文件中允许 print
"*.ipynb" = ["T201"]

5.1.3 自定义规则忽略模式

[tool.ruff.lint]
# 允许某些变量名的未使用导入 (如 typing 的 TYPE_CHECKING)
ignore-init-module-imports = true

# 不检查赋值表达式中未使用的变量
# a = [x for x in range(10) if x > 5]  ← x 被正常使用
dummy-variable-rgx = "^_+|^(_$|unused_)"  # _开头的变量不报告

[tool.ruff.lint.flake8-type-checking]
# 强制将 typing-only import 移入 TYPE_CHECKING
strict = true

5.1.4 Ruff 导出规则配置

# 将当前配置导出为配置文件
ruff check --show-settings

# 生成建议的 pyproject.toml
ruff config --format pyproject

# 查看某个文件上应用了哪些规则
ruff check --show-files file.py

5.2 性能调优

5.2.1 多层级缓存

# Ruff 自动缓存结果到 ~/.cache/ruff/
# 第二次运行几乎瞬时完成

# 查看缓存位置
ruff check --show-files . | head

# 清除缓存
ruff clean

# CI 中使用缓存 (GitHub Actions)
# .github/workflows/lint.yml
- uses: actions/cache@v4
  with:
    path: ~/.cache/ruff
    key: ruff-${{ hashFiles('pyproject.toml') }}-${{ github.sha }}
    restore-keys: ruff-${{ hashFiles('pyproject.toml') }}-

5.2.2 使用 --preview 模式

# --preview 启用尚未稳定的新规则
ruff check --preview .
ruff format --preview .

# pyproject.toml 中设置
[tool.ruff.lint]
preview = true

5.3 实战:新项目 Ruff 配置方案

# ── 最小生产级配置 ──
[tool.ruff]
target-version = "py311"
line-length = 100
extend-exclude = [
    ".git",
    ".venv",
    "build",
    "dist",
    "migrations",
    "node_modules",
    "__pycache__",
]

[tool.ruff.lint]
select = [
    "F",      # Pyflakes: 基础错误检测
    "E", "W", # pycodestyle: 代码风格
    "I",      # isort: import 排序
    "UP",     # pyupgrade: 语法现代化
    "B",      # bugbear: 常见陷阱
    "SIM",    # flake8-simplify: 简化代码
    "TCH",    # 类型检查导入
    "T20",    # flake8-print: 防止遗留 print
    "RUF",    # Ruff 专有规则
    "C4",     # comprehensions: 推导式优化
    "N",      # pep8-naming: 命名规范
]

ignore = []
fixable = ["ALL"]
unfixable = []

[tool.ruff.lint.isort]
known-first-party = ["myapp"]

[tool.ruff.lint.flake8-tidy-imports]
ban-relative-imports = "parents"

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
docstring-code-format = true

5.4 常见问题与排障

5.4.1 问题排查流程

确实没有错误

规则未启用

文件被 exclude

极少数情况

配置差异

版本不一致

缓存问题

ruff check 没有输出?

✅ 代码质量好!

检查 pyproject.toml 的 select 字段

检查 exclude 和 extend-exclude

ruff format 和 Black 输出不同?

升级到最新版 Ruff

对比 line-length / quote-style 设置

CI 中 ruff 报错但本地不报?

锁定 ruff 版本: pip install ruff==0.6.x

ruff clean && ruff check .

5.4.2 常见误报与处理

# 误报 1: TYPE_CHECKING 导入
from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from myapp.models import User  # Ruff: F401 unused import
# 解决: 启用 TCH 规则, Ruff 会自动理解 TYPE_CHECKING

# 误报 2: @override 装饰器
from typing import override
class Child(Parent):
    @override
    def method(self): ...  # 如果工具不能识别 override → F811
# 解决: target-version >= "py312" 时自动识别

# 误报 3: dataclass 的 __init__
from dataclasses import dataclass
@dataclass
class Config:
    name: str = "default"  # Ruff: B008 mutable default in function
# 解决: Ruff 识别 dataclass, 不会误报 (0.3.x+)

5.5 小结

知识点 掌握程度 核心要点
Ruff 定位 掌握 Rust 编写的极速 Python linter + formatter,替代 Flake8/Black/isort
安装使用 熟练 pip install ruffruff check --fix
规则体系 掌握 700+ 规则,按前缀分类 (F/E/I/UP/B/SIM/PL…)
pyproject.toml 配置 熟练 select/ignore/per-file-ignores 三段式管理
Formatter 掌握 ruff format --check --diff .,兼容 Black 99.9%
VS Code 集成 掌握 保存时自动 lint + fix + format + import 整理
Pre-commit 掌握 提交前自动检查,零等待
CI/CD 掌握 GitHub Actions / GitLab CI 一行安装即可
迁移 掌握 Flake8→Ruff 规则映射表,配置一键转换
进阶技巧 理解 行级忽略、per-file-ignores、缓存优化

推荐资源

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐