痛点
运维团队的 Python 脚本越写越多——监控采集、自动化部署、AI Agent 工具链、数据清洗。代码质量工具也越装越多:Flake8 做 lint、Black 做格式化、isort 排 import、Bandit 查安全问题、pyupgrade 升语法。5 个工具各有配置文件,CI 流水线里串行跑一遍要 40 秒+,本地 pre-commit 更是慢到开发者直接跳过。
更痛的是配置碎片化:.flake8 用 INI 格式,pyproject.toml 里塞 Black 和 isort 的配置,Bandit 又有自己的 YAML——规则冲突时排查成本极高。
方案:Ruff 一个工具全替代
Ruff 是 Astral 团队用 Rust 编写的 Python linter + formatter。核心优势:
| 对比项 | 传统工具链 | Ruff |
|---|---|---|
| 速度 | Flake8 检查 10 万行约 30s | 同规模 < 0.3s(快 100 倍+) |
| 工具数量 | 5+ 个独立工具 | 1 个二进制搞定 |
| 配置文件 | 散落 3-4 个文件 | 统一 pyproject.toml |
| 规则覆盖 | 各管各的 | 800+ 条规则,覆盖 Flake8、isort、pyupgrade、Bandit 等 |
| 自动修复 | Black 格式化 + 手动改 lint | ruff check --fix + ruff format 一条龙 |
实操步骤
第 1 步:安装与基础检查
# 推荐用 pipx 或 uv 全局安装
pip install ruff
# 或
uv tool install ruff
# 验证安装
ruff --version
# ruff 0.9.x
# 对项目目录执行 lint 检查
ruff check .
# 自动修复可安全修复的问题
ruff check --fix .
# 格式化代码(替代 Black)
ruff format .
在一个典型的运维脚本仓库(200 个 .py 文件、约 3 万行)上实测:
# Flake8
time flake8 .
# real 0m8.320s
# Ruff
time ruff check .
# real 0m0.067s
快了 124 倍,而且规则更全面。
第 2 步:配置 pyproject.toml 统一规则
在项目根目录的 pyproject.toml 中集中配置:
[tool.ruff]
# 目标 Python 版本,影响语法升级建议
target-version = "py311"
# 行宽,与团队规范一致
line-length = 120
# 排除目录
exclude = ["migrations", "venv", ".venv"]
[tool.ruff.lint]
# 启用的规则集
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # Pyflakes
"I", # isort(import 排序)
"UP", # pyupgrade(语法现代化)
"S", # Bandit(安全检查)
"B", # flake8-bugbear(常见 bug 模式)
"SIM", # flake8-simplify(简化写法)
"RUF", # Ruff 自有规则
]
# 忽略特定规则
ignore = [
"S101", # 允许 assert(测试代码需要)
"S603", # subprocess 调用误报(运维脚本刚需)
]
[tool.ruff.lint.per-file-ignores]
# 测试文件放宽安全检查
"tests/**/*.py" = ["S"]
[tool.ruff.format]
# 引号风格
quote-style = "double"
# 缩进风格
indent-style = "space"
这一个配置块替代了原来 .flake8、pyproject.toml 中 Black/isort 的分散配置。
第 3 步:集成 CI/CD 和 pre-commit
GitHub Actions 集成:
# .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
with:
args: "check --output-format=github"
- uses: astral-sh/ruff-action@v3
with:
args: "format --check"
整个 lint 步骤从原来的 40 秒降到 3 秒以内,且官方 Action 自带缓存。
pre-commit 集成:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.6
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
本地提交时自动检查 + 修复,开发者体感几乎零延迟。
避坑指南
1. 从现有项目迁移时不要一次性开启所有规则
Ruff 有 800+ 条规则,全开会产生海量告警。推荐策略:先用 select = ["E", "F", "I"] 基础规则集上线,稳定后逐步添加 UP、S、B 等。用 ruff check --statistics 查看各规则触发频率,按优先级逐批修复。
2. ruff format 和 Black 输出不完全一致
Ruff formatter 兼容 Black 95%+ 的风格,但在部分边缘情况(如魔法逗号 trailing comma、长字符串折行)处理略有差异。迁移时建议一次性跑 ruff format . 并提交,后续就以 Ruff 为准,避免混用两个格式化器。
3. 运维脚本中 subprocess 和 os.system 会触发安全规则
Bandit 规则集(S)会对 subprocess.run(shell=True) 等调用报警。运维脚本中这是刚需,不能一刀切禁用。正确做法是在 pyproject.toml 中按目录豁免:
[tool.ruff.lint.per-file-ignores]
"scripts/**/*.py" = ["S603", "S607"] # 运维脚本目录放行子进程调用
总结
Ruff 用一个 Rust 二进制替代了 Python 代码质量工具链的 5+ 个组件,检查速度提升两个数量级,配置集中到 pyproject.toml 一处。对于写大量 Python 脚本的运维团队,迁移收益明确:CI 流水线加速、pre-commit 体验优化、配置维护成本归零。建议新项目直接用 Ruff,存量项目分批迁移——先替 Flake8 + isort,再替 Black,最后启用安全规则替 Bandit。