Python工程化开发 python

本技能专注于Python工程化开发实践,涵盖类型安全、代码质量、测试驱动开发和现代开发工具链。核心内容包括:使用mypy进行严格的类型检查确保代码可靠性;通过ruff实现代码格式化和静态分析;采用pytest构建完善的测试体系;遵循TDD(测试驱动开发)原则;实施依赖注入、结果模式等设计模式;建立标准化的项目结构和CI/CD流程。适用于构建高质量、可维护的Python应用程序,特别适合企业级项目开发、API服务和数据管道等场景。关键词:Python开发、类型安全、测试驱动开发、代码质量、工程化实践、CI/CD、mypy、ruff、pytest、TDD。

后端开发 0 次安装 0 次浏览 更新于 3/5/2026

name: python description: 使用ruff、mypy、pytest进行Python开发 - TDD与类型安全

Python技能

使用base.md加载


类型提示

  • 在所有函数签名中使用类型提示
  • 使用typing模块处理复杂类型
  • 在CI中运行mypy --strict
def process_user(user_id: int, options: dict[str, Any] | None = None) -> User:
    ...

项目结构

project/
├── src/
│   └── package_name/
│       ├── __init__.py
│       ├── core/           # 纯业务逻辑
│       │   ├── __init__.py
│       │   ├── models.py   # Pydantic模型/数据类
│       │   └── services.py # 纯函数
│       ├── infra/          # 副作用
│       │   ├── __init__.py
│       │   ├── api.py      # FastAPI路由
│       │   └── db.py       # 数据库操作
│       └── utils/          # 共享工具
├── tests/
│   ├── unit/
│   └── integration/
├── pyproject.toml
└── CLAUDE.md

工具链(必需)

# pyproject.toml
[tool.ruff]
line-length = 100
select = ["E", "F", "I", "N", "W", "UP"]

[tool.mypy]
strict = true

[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "--cov=src --cov-report=term-missing --cov-fail-under=80"

使用Pytest测试

# tests/unit/test_services.py
import pytest
from package_name.core.services import calculate_total

class TestCalculateTotal:
    def test_returns_sum_of_items(self):
        # 准备
        items = [{"price": 10}, {"price": 20}]
        
        # 执行
        result = calculate_total(items)
        
        # 断言
        assert result == 30

    def test_returns_zero_for_empty_list(self):
        assert calculate_total([]) == 0

    def test_raises_on_invalid_item(self):
        with pytest.raises(ValueError):
            calculate_total([{"invalid": "item"}])

GitHub Actions

name: Python质量门禁

on: [push, pull_request]

jobs:
  quality:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: 设置Python环境
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'
          
      - name: 安装依赖
        run: |
          pip install -e ".[dev]"
          
      - name: 代码检查(Ruff)
        run: ruff check .
        
      - name: 格式检查(Ruff)
        run: ruff format --check .
        
      - name: 类型检查(mypy)
        run: mypy src/
        
      - name: 测试与覆盖率
        run: pytest

预提交钩子

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.8.0
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format

  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.13.0
    hooks:
      - id: mypy
        additional_dependencies: [pydantic]
        args: [--strict]

  - repo: local
    hooks:
      - id: pytest
        name: pytest
        entry: pytest tests/unit -x --tb=short
        language: system
        pass_filenames: false
        always_run: true

安装与设置:

pip install pre-commit
pre-commit install

设计模式

使用Pydantic进行数据验证

from pydantic import BaseModel, Field

class CreateUserRequest(BaseModel):
    email: str = Field(..., min_length=5)
    name: str = Field(..., max_length=100)

依赖注入

# 不要在业务逻辑中直接导入依赖
# 通过参数传入

# 错误示例
from .db import database
def get_user(user_id: int) -> User:
    return database.fetch(user_id)

# 正确示例
def get_user(user_id: int, db: Database) -> User:
    return db.fetch(user_id)

结果模式(核心逻辑中不使用异常)

from dataclasses import dataclass

@dataclass
class Result[T]:
    value: T | None
    error: str | None
    
    @property
    def is_ok(self) -> bool:
        return self.error is None

Python反模式

  • from module import *
  • ❌ 可变默认参数
  • ❌ 空的except:子句
  • ❌ 使用type: ignore而不加解释
  • ❌ 使用全局变量存储状态
  • ❌ 函数足够时使用类