Python 静态检查与 Ruff
用 Ruff 做高速 lint/format,并结合类型检查器形成静态质量门禁。
#concept
#growing
#dev
#python
#python
[!info] related notes
Python 静态检查与 Ruff
这个概念为什么出现
风格争议与低级缺陷(未使用导入、危险默认、简化比较)不应靠人工 review 反复抓。Ruff 以 Rust 实现提供极快 lint/format;类型检查器补接口契约。
[!abstract] 一句话理解 Ruff 统一 lint/format 规则并快速反馈;与 pyright/mypy 分工:风格与缺陷 vs 类型契约。
最小可运行示例
先把示例放进业务场景,再看代码:
场景:演示“未使用变量”类问题为何该自动抓
# lint_smell_demo.py
# 业务意图:展示可被 lint 抓住的坏味道(教学文件)。
# 教学点:静态工具在 CI 挡低级问题。
def handle(order_id: str) -> str:
unused = 1 # Ruff/F841 会抱怨
return f"ok:{order_id}"
if __name__ == "__main__":
print(handle("O1"))
建议运行:
python lint_smell_demo.py
ruff check --isolated --select F841 lint_smell_demo.py # 需已安装 Ruff
# 此教学文件预期报告 F841 并以非零状态退出
期望输出:
ok:O1
上面的 Python 执行仍输出 ok:O1;静态检查则应报 F841。—isolated 和 —select 用于固定演示范围,项目 CI 应使用自己的配置。
结合场景再看三个关注点
- 能跑 ≠ 干净。
- lint 规则要团队配置,避免噪声。
- format 结束风格战争。
核心概念与准确模型
- ruff check 检查已启用规则;ruff format 负责格式化,不代替 lint。CI 用 ruff format —check 避免修改文件。
- pyproject 配置规则
- pre-commit / CI 门禁
- 类型检查单独通道
边界情况与反直觉行为
- 自动修复需检查 diff;并非每条规则都可安全修复,F841 的修复可能移除注释,标为 unsafe。不要为本示例机械开启全部 unsafe fixes。
- 生成代码 可 per-file ignore。
- 与 black/isort 历史迁移。
常见误区
[!warning] 常见误区:lint 替代测试与设计 错误理解:全绿即正确。
正确模型:静态层只是多层质量之一。
工程实践
- 新项目默认 Ruff
- 与编辑器保存联动
- 规则变更要有变更说明
本节总结
高速静态反馈让人类 review 聚焦设计。Ruff + 类型检查是现代默认组合。
自测题
- Ruff 与类型检查器分工?
- 为何要 CI 跑而不是只靠本地?
参考答案
- Ruff 偏风格/代码异味;类型检查偏接口契约。
- 保证未装钩子的提交也被门禁挡住。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| Ruff | 文档 | 工具 |
| pyright | 文档 | 类型检查 |