CI/CD 与项目规范
从个人脚本到团队项目——代码规范、自动化检查、持续集成,让 Python 项目可维护。
工程化全景
graph TD
ENG[Python 工程化] --> STRUCT[项目结构]
ENG --> LINT[代码规范]
ENG --> CI[持续集成]
ENG --> PKG[打包发布]
STRUCT --> SRC[src 布局]
STRUCT --> CONF[配置管理]
LINT --> RUFF[ruff]
LINT --> MYPY[mypy]
LINT --> PRE[pre-commit]
CI --> GHA[GitHub Actions]
CI --> TEST[自动测试]
CI --> COV[覆盖率]
PKG --> PYPI[PyPI 发布]
PKG --> DOCKER[Docker 镜像]
style ENG fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
style CI fill:#c8e6c9,stroke:#388e3c,stroke-width:2px
项目结构模板
"""
推荐的 Python 项目结构
"""
PROJECT_STRUCTURE = """
my-project/
├── src/
│ └── my_project/
│ ├── __init__.py
│ ├── main.py
│ ├── config.py
│ ├── models/
│ │ └── __init__.py
│ ├── services/
│ │ └── __init__.py
│ └── utils/
│ └── __init__.py
├── tests/
│ ├── conftest.py # pytest fixtures
│ ├── test_main.py
│ └── test_services/
│ └── test_user.py
├── pyproject.toml # 项目配置(统一)
├── requirements.txt # 生产依赖
├── requirements-dev.txt # 开发依赖
├── Dockerfile
├── .github/
│ └── workflows/
│ └── ci.yml
├── .pre-commit-config.yaml
└── README.md
"""
# pyproject.toml 示例
PYPROJECT_TOML = """
[project]
name = "my-project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
"fastapi>=0.100",
"uvicorn>=0.20",
"sqlalchemy>=2.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.0",
"pytest-cov>=4.0",
"ruff>=0.1.0",
"mypy>=1.0",
"pre-commit>=3.0",
]
[tool.ruff]
target-version = "py312"
line-length = 100
[tool.ruff.lint]
select = ["E", "F", "W", "I", "N", "UP"]
[tool.mypy]
python_version = "3.12"
strict = true
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "-v --cov=src --cov-report=term-missing"
"""
pre-commit 自动检查
"""
pre-commit:提交前自动检查代码质量
"""
PRE_COMMIT_CONFIG = """
# .pre-commit-config.yaml
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.0
hooks:
- id: ruff # lint
args: [--fix]
- id: ruff-format # format
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.8.0
hooks:
- id: mypy
additional_dependencies: [types-requests]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
"""
SETUP_COMMANDS = """
# 安装
pip install pre-commit
# 初始化(在 .git 目录中创建钩子)
pre-commit install
# 手动运行所有检查
pre-commit run --all-files
# 提交时自动运行
git commit -m "feat: add feature"
# → 自动运行 ruff + mypy + 格式化
"""
GitHub Actions CI
"""
GitHub Actions 持续集成配置
"""
CI_WORKFLOW = """
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install -r requirements-dev.txt
- name: Lint with ruff
run: |
ruff check src/
ruff format --check src/
- name: Type check with mypy
run: mypy src/ --strict
- name: Test with pytest
run: pytest --cov --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
file: coverage.xml
"""
# Makefile 常用命令
MAKEFILE = """
# Makefile
.PHONY: dev test lint format clean
dev:
pip install -e ".[dev]"
pre-commit install
test:
pytest -v --cov --cov-report=term-missing
lint:
ruff check src/ tests/
mypy src/ --strict
format:
ruff check --fix src/ tests/
ruff format src/ tests/
clean:
rm -rf dist/ build/ *.egg-info
find . -type d -name __pycache__ -exec rm -rf {} +
"""
配置管理
"""
环境配置:pydantic-settings 管理
"""
from pydantic_settings import BaseSettings
from functools import lru_cache
class Settings(BaseSettings):
"""应用配置,自动读取环境变量"""
app_name: str = "My App"
debug: bool = False
database_url: str = "sqlite:///app.db"
secret_key: str = "change-me"
redis_url: str = "redis://localhost:6379"
# API Keys
openai_api_key: str = ""
model_config = {
"env_file": ".env",
"env_file_encoding": "utf-8",
}
@lru_cache
def get_settings() -> Settings:
"""单例获取配置"""
return Settings()
# 使用
settings = get_settings()
print(f"App: {settings.app_name}, Debug: {settings.debug}")
工具链总结
| 工具 | 用途 | 命令 |
|---|---|---|
| ruff | Lint + Format | ruff check --fix / ruff format |
| mypy | 类型检查 | mypy src/ --strict |
| pytest | 测试 | pytest -v --cov |
| pre-commit | 提交钩子 | pre-commit run --all-files |
| GitHub Actions | CI/CD | Push 自动运行 |
| pydantic-settings | 配置管理 | 环境变量 + .env |
本章小结
| 知识点 | 要点 |
|---|---|
| 项目结构 | src 布局 + pyproject.toml |
| 代码规范 | ruff (lint+format) + mypy (类型) |
| 自动化 | pre-commit 提交前检查 |
| CI/CD | GitHub Actions 矩阵测试 |
| 配置 | pydantic-settings 环境变量 |
下一章:实战项目——数据管道与 API 服务。