课题20:项目代码规范与格式化
难度:低 | 类型:项目实战 | 源文件:
.pre-commit-config.yaml,docs/CODING_STANDARDS.md,scripts/lint_check.sh| 行数:~200 状态:✅ 已完成
概述
为项目引入代码格式化工具(Black、isort)和静态检查工具(Ruff、mypy),统一代码风格,确保质量。
理解背景
是什么?
代码规范体系确保 ScratchV 项目的所有代码风格一致、类型安全、无低级错误。包含自动化工具链:
| 工具 | 用途 | 触发方式 |
|---|---|---|
| Black | Python 代码格式化 | git commit 时自动 |
| isort | import 排序 | git commit 时自动 |
| Ruff | 快速 lint(替代 flake8) | git commit 时自动 |
| mypy | 静态类型检查 | git commit 时自动 |
| pre-commit | 钩子管理器 | 安装后自动运行 |
为什么?
- 一致性:10 个贡献者的代码看起来像一个人写的
- 减少 review 负担:格式化问题自动修复,reviewer 只需关注逻辑
- 提前发现 bug:类型检查和 lint 在 commit 之前就拦下低级错误
核心概念
pre-commit 钩子
pre-commit 钩子
每次 git commit 时自动运行配置的检查工具。如果有问题:
- Black/isort/Ruff → 自动修复并阻止 commit(需要重新 add + commit)
- mypy → 报告类型错误,需要手动修复
配置要点
# .pre-commit-config.yaml
repos:
- repo: https://github.com/psf/black
rev: 24.x
hooks:
- id: black
args: [--line-length=88, --target-version=py312]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.x
hooks:
- id: ruff
args: [--fix]
详细任务
- 配置
pyproject.toml,添加Black和isort配置。
- 配置Ruff(或Flake8)进行代码风格检查,定义忽略规则。
- 配置mypy进行静态类型检查,为关键模块添加类型注解。
- 添加pre-commit hooks,确保提交前自动格式化和检查。
- 在CI中增加lint步骤(结合课题6的CI)。
- 格式化整个项目代码库,修复所有lint错误。
交付产物
pyproject.toml配置文件
.pre-commit-config.yaml
- CI配置文件中的lint作业
- 文档:代码规范指南、如何运行格式化和检查
代码走读
安装
pip install pre-commit
pre-commit install
手动运行
# 对所有文件运行所有检查
pre-commit run --all-files
# 只运行 Black
pre-commit run black --all-files
# 用便捷脚本
bash scripts/lint_check.sh # 只检查
bash scripts/lint_check.sh --fix # 自动修复
bash scripts/lint_check.sh --all # 包含测试文件
编码规范速查
# .pre-commit-config.yaml
repos:
- repo: https://github.com/psf/black
rev: 24.x
hooks:
- id: black
args: [--line-length=88, --target-version=py312]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.x
hooks:
- id: ruff
args: [--fix]
- 配置
pyproject.toml,添加Black和isort配置。 - 配置Ruff(或Flake8)进行代码风格检查,定义忽略规则。
- 配置mypy进行静态类型检查,为关键模块添加类型注解。
- 添加pre-commit hooks,确保提交前自动格式化和检查。
- 在CI中增加lint步骤(结合课题6的CI)。
- 格式化整个项目代码库,修复所有lint错误。
交付产物
pyproject.toml配置文件
.pre-commit-config.yaml
- CI配置文件中的lint作业
- 文档:代码规范指南、如何运行格式化和检查
代码走读
安装
pip install pre-commit
pre-commit install
手动运行
# 对所有文件运行所有检查
pre-commit run --all-files
# 只运行 Black
pre-commit run black --all-files
# 用便捷脚本
bash scripts/lint_check.sh # 只检查
bash scripts/lint_check.sh --fix # 自动修复
bash scripts/lint_check.sh --all # 包含测试文件
编码规范速查
pyproject.toml配置文件.pre-commit-config.yaml安装
pip install pre-commit
pre-commit install
手动运行
# 对所有文件运行所有检查
pre-commit run --all-files
# 只运行 Black
pre-commit run black --all-files
# 用便捷脚本
bash scripts/lint_check.sh # 只检查
bash scripts/lint_check.sh --fix # 自动修复
bash scripts/lint_check.sh --all # 包含测试文件
编码规范速查
pip install pre-commit
pre-commit install
# 对所有文件运行所有检查
pre-commit run --all-files
# 只运行 Black
pre-commit run black --all-files
# 用便捷脚本
bash scripts/lint_check.sh # 只检查
bash scripts/lint_check.sh --fix # 自动修复
bash scripts/lint_check.sh --all # 包含测试文件
编码规范速查
| 规范 | 要求 |
|---|---|
| 导入 | 使用 scratchv.* 绝对导入,不用相对导入(from . import) |
| 命名 | 模块 snake_case,类 PascalCase,函数/变量 snake_case |
| 类型提示 | 所有公开 API 必须有 type hints |
| Docstring | 模块级 + 类级 + 方法级,用 """...""" |
| 行宽 | 88 字符(Black 默认) |
lint_check.sh 核心
# 只检查 scratchv/ 目录
ruff check scratchv/
mypy scratchv/ --ignore-missing-imports --follow-imports=silent
# --fix: 同时运行 Black 和 isort 自动修复
black scratchv/ tests/
isort scratchv/ tests/
CI 集成
# .github/workflows/ci.yml
- name: Lint
run: |
pip install ruff mypy
ruff check .
mypy scratchv/ --ignore-missing-imports
动手练习
练习 1: 安装 pre-commit
# 只检查 scratchv/ 目录
ruff check scratchv/
mypy scratchv/ --ignore-missing-imports --follow-imports=silent
# --fix: 同时运行 Black 和 isort 自动修复
black scratchv/ tests/
isort scratchv/ tests/
# .github/workflows/ci.yml
- name: Lint
run: |
pip install ruff mypy
ruff check .
mypy scratchv/ --ignore-missing-imports
动手练习
练习 1: 安装 pre-commit
在本地项目安装 pre-commit install,提交一个代码改动,观察自动检查过程。
练习 2: 修复 lint 问题
运行 ruff check .,挑一个 warning 手动修复。
练习 3: 添加类型提示
找一个没写类型提示的公开函数,添加正确的 type hints,运行 mypy 确认通过。
常见坑
| 坑 | 说明 |
|---|---|
| pre-commit 未安装 | 如果只 pip install pre-commit 但没运行 pre-commit install,钩子不会触发 |
| Black vs isort 冲突 | 两个工具对 import 排序的默认规则不同——确保 isort 使用 profile=black |
| mypy 误报 | 第三方库(如 onnx)可能没有类型存根,用 --ignore-missing-imports 跳过 |
| CI 环境差异 | CI 可能用不同版本的 mypy/ruff,保持 pyproject.toml 中的版本约束 |
进阶阅读
- Black 文档 | Ruff 文档
- CODING_STANDARDS — 完整编码规范
- 相关课题: 课题9:DSL错误提示美化器(另一个"开发者体验"工具)
12周每周目标
- W1:学习Black/isort/Ruff/mypy的用法和配置方法,本地安装测试。
- W2:编写
pyproject.toml,配置Black行长度(如88)、isort配置。
- W3:配置Ruff,选择要启用的检查规则(如E、F、W),定义忽略规则。
- W4:在本地运行Black和isort格式化整个项目,提交PR。
- W5:配置mypy,为项目根目录添加
mypy.ini,先忽略错误较多的模块。
- W6:为关键模块(如
ir.py、dsl_parser.py)添加类型注解。
- W7:逐步为其他模块添加类型注解,修复mypy错误。
- W8:安装pre-commit,编写
.pre-commit-config.yaml,包含black、isort、ruff、mypy。
- W9:测试pre-commit hooks,确保每次提交自动运行。
- W10:在CI配置中添加lint作业(使用ruff和mypy),与课题6的CI集成。
- W11:修复CI中发现的剩余lint错误,确保CI通过。
- W12:撰写代码规范文档,包含如何安装pre-commit、如何运行检查。
- W1:学习Black/isort/Ruff/mypy的用法和配置方法,本地安装测试。
- W2:编写
pyproject.toml,配置Black行长度(如88)、isort配置。 - W3:配置Ruff,选择要启用的检查规则(如E、F、W),定义忽略规则。
- W4:在本地运行Black和isort格式化整个项目,提交PR。
- W5:配置mypy,为项目根目录添加
mypy.ini,先忽略错误较多的模块。 - W6:为关键模块(如
ir.py、dsl_parser.py)添加类型注解。 - W7:逐步为其他模块添加类型注解,修复mypy错误。
- W8:安装pre-commit,编写
.pre-commit-config.yaml,包含black、isort、ruff、mypy。 - W9:测试pre-commit hooks,确保每次提交自动运行。
- W10:在CI配置中添加lint作业(使用ruff和mypy),与课题6的CI集成。
- W11:修复CI中发现的剩余lint错误,确保CI通过。
- W12:撰写代码规范文档,包含如何安装pre-commit、如何运行检查。