mcpField
P
python-anti-patterns

python-anti-patterns

github.com/full-stack-skills测试与质量395 次安装4 周前更新
代码仓库

关于 python-anti-patterns

python-anti-patterns 是供 Python 开发者审查代码的反模式清单,涵盖基础设施、架构、错误处理、资源、类型和测试等方面。它通过问题示例、改进方向和检查项,帮助在合并前审查或重构时发现常见问题。

主要功能

  1. 01检查重试与配置管理问题
  2. 02识别架构和错误处理反模式
  3. 03检查资源使用与异步阻塞
  4. 04涵盖类型标注和测试边界

适用场景

  1. 01合并前审查 Python 代码
  2. 02排查可能由不良实践导致的问题
  3. 03重构遗留代码并建立团队规范
  4. 04学习 Python 常见编码问题及修正方式

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/full-stack-skills/python-skills --skill python-anti-patterns

安装后在 Claude Code 中输入/python-anti-patterns确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

LICENSE.txt
agents/
openai.yaml
examples/
advanced-usage.md
basic-usage.md
integration.md

详细介绍

来源声明:本技能内容源自 wshobson/agents (MIT License, Copyright (c) 2024 Seth Hobson;完整许可文本见同目录 LICENSE.txt)。 使用、修改与再分发须遵守该 MIT 许可条款并保留版权声明。

中文描述

本技能提供全栈开发相关的最佳实践和模式指导。


name: python-anti-patterns description: 在审查 Python 代码、避免常见反模式时使用本技能。可将其用作代码审查清单、完成实现前的检查清单,或用于调试可能源于已知不良实践的问题。

Python 反模式检查清单

一份关于 Python 代码中常见错误和反模式的参考清单。完成实现前请查看此清单,以便及早发现问题。

何时使用本技能

  • 合并前审查代码
  • 调试难以理解的问题
  • 教授或学习 Python 最佳实践
  • 制定团队编码规范
  • 重构遗留代码

**注意:**本技能侧重于应避免的做法。有关良好模式和架构的指导,请参阅 python-design-patterns 技能。

基础设施反模式

分散的超时/重试逻辑
# BAD: Timeout logic duplicated everywhere
def fetch_user(user_id):
    try:
        return requests.get(url, timeout=30)
    except Timeout:
        logger.warning("Timeout fetching user")
        return None

def fetch_orders(user_id):
    try:
        return requests.get(url, timeout=30)
    except Timeout:
        logger.warning("Timeout fetching orders")
        return None

**修复方法:**通过装饰器或客户端封装集中处理。

# GOOD: Centralized retry logic
@retry(stop=stop_after_attempt(3), wait=wait_exponential())
def http_get(url: str) -> Response:
    return requests.get(url, timeout=30)
重复重试
# BAD: Retrying at multiple layers
@retry(max_attempts=3)  # Application retry
def call_service():
    return client.request()  # Client also has retry configured!

**修复方法:**只在一个层级进行重试。了解基础设施的重试行为。

硬编码配置
# BAD: Secrets and config in code
DB_HOST = "prod-db.example.com"
API_KEY = "sk-12345"

def connect():
    return psycopg.connect(f"host={DB_HOST}...")

**修复方法:**使用带类型的环境变量设置。

# GOOD
from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    db_host: str = Field(alias="DB_HOST")
    api_key: str = Field(alias="API_KEY")

settings = Settings()

架构反模式

暴露内部类型
# BAD: Leaking ORM model to API
@app.get("/users/{id}")
def get_user(id: str) -> UserModel:  # SQLAlchemy model
    return db.query(UserModel).get(id)

**修复方法:**使用 DTO/响应模型。

# GOOD
@app.get("/users/{id}")
def get_user(id: str) -> UserResponse:
    user = db.query(UserModel).get(id)
    return UserResponse.from_orm(user)
I/O 与业务逻辑混杂
# BAD: SQL embedded in business logic
def calculate_discount(user_id: str) -> float:
    user = db.query("SELECT * FROM users WHERE id = ?", user_id)
    orders = db.query("SELECT * FROM orders WHERE user_id = ?", user_id)
    # Business logic mixed with data access
    if len(orders) > 10:
        return 0.15
    return 0.0

**修复方法:**使用仓储模式。保持业务逻辑纯粹。

# GOOD
def calculate_discount(user: User, orders: list[Order]) -> float:
    # Pure business logic, easily testable
    if len(orders) > 10:
        return 0.15
    return 0.0

错误处理反模式

裸异常处理
# BAD: Swallowing all exceptions
try:
    process()
except Exception:
    pass  # Silent failure - bugs hidden forever

**修复方法:**捕获特定异常,并适当地记录或处理。

# GOOD
try:
    process()
except ConnectionError as e:
    logger.warning("Connection failed, will retry", error=str(e))
    raise
except ValueError as e:
    logger.error("Invalid input", error=str(e))
    raise BadRequestError(str(e))
忽略部分失败
# BAD: Stops on first error
def process_batch(items):
    results = []
    for item in items:
        result = process(item)  # Raises on error - batch aborted
        results.append(result)
    return results

**修复方法:**同时记录成功和失败的结果。

# GOOD
def process_batch(items) -> BatchResult:
    succeeded = {}
    failed = {}
    for idx, item in enumerate(items):
        try:
            succeeded[idx] = process(item)
        except Exception as e:
            failed[idx] = e
    return BatchResult(succeeded, failed)
缺少输入验证
# BAD: No validation
def create_user(data: dict):
    return User(**data)  # Crashes deep in code on bad input

**修复方法:**在 API 边界尽早进行验证。

# GOOD
def create_user(data: dict) -> User:
    validated = CreateUserInput.model_validate(data)
    return User.from_input(validated)

资源反模式

未关闭资源
# BAD: File never closed
def read_file(path):
    f = open(path)
    return f.read()  # What if this raises?

**修复方法:**使用上下文管理器。

# GOOD
def read_file(path):
    with open(path) as f:
        return f.read()
在异步代码中阻塞
# BAD: Blocks the entire event loop
async def fetch_data():
    time.sleep(1)  # Blocks everything!
    response = requests.get(url)  # Also blocks!

**修复方法:**使用原生异步库。

# GOOD
async def fetch_data():
    await asyncio.sleep(1)
    async with httpx.AsyncClient() as client:
        response = await client.get(url)

类型安全反模式

缺少类型提示
# BAD: No types
def process(data):
    return data["value"] * 2

**修复方法:**为所有公共函数添加类型注解。

# GOOD
def process(data: dict[str, int]) -> int:
    return data["value"] * 2
集合未标注类型
# BAD: Generic list without type parameter
def get_users() -> list:
    ...

**修复方法:**使用类型参数。

# GOOD
def get_users() -> list[User]:
    ...

测试反模式

只测试正常路径
# BAD: Only tests success case
def test_create_user():
    user = service.create_user(valid_data)
    assert user.id is not None

**修复方法:**测试错误条件和边界情况。

# GOOD
def test_create_user_success():
    user = service.create_user(valid_data)
    assert user.id is not None

def test_create_user_invalid_email():
    with pytest.raises(ValueError, match="Invalid email"):
        service.create_user(invalid_email_data)

def test_create_user_duplicate_email():
    service.create_user(valid_data)
    with pytest.raises(ConflictError):
        service.create_user(valid_data)
过度模拟
# BAD: Mocking everything
def test_user_service():
    mock_repo = Mock()
    mock_cache = Mock()
    mock_logger = Mock()
    mock_metrics = Mock()
    # Test doesn't verify real behavior

**修复方法:**为关键路径编写集成测试。只模拟外部服务。

快速审查清单

完成代码前,请确认:

  • 没有分散的超时/重试逻辑(已集中处理)
  • 没有重复重试(应用程序 + 基础设施)
  • 没有硬编码配置或密钥
  • 没有暴露内部类型(ORM 模型、protobuf)
  • I/O 与业务逻辑没有混杂
  • 没有裸 except Exception: pass
  • 批处理中的部分失败没有被忽略
  • 输入验证齐全
  • 资源均已关闭(使用上下文管理器)
  • 异步代码中没有阻塞调用
  • 所有公共函数都有类型提示
  • 集合都标注了类型参数
  • 已测试错误路径
  • 已覆盖边界情况

常见修复方法摘要

反模式修复方法
分散的重试逻辑集中使用装饰器处理
硬编码配置环境变量 + pydantic-settings
暴露 ORM 模型DTO/响应模式
I/O 与逻辑混杂仓储模式
裸 except捕获特定异常
批处理遇错即停返回包含成功和失败结果的 BatchResult
没有验证在边界处使用 Pydantic 进行验证
未关闭资源上下文管理器
在异步代码中阻塞原生异步库
缺少类型为所有公共 API 添加类型注解
只测试正常路径测试错误和边界情况

能力边界

✅ 擅长处理
  • 全栈开发相关的最佳实践
  • 代码架构设计指导
  • 性能优化建议
⚠️ 需要素材
  • 具体的项目上下文
  • 技术栈信息
❌ 超出范围
  • 非技术领域的业务决策
  • 具体的代码实现(仅提供指导)

工作流程

Step 1: 需求分析

理解项目需求和技术约束

Step 2: 架构设计

设计系统架构和组件划分

Step 3: 实现指导

提供具体的实现建议和代码模式

Step 4: 代码审查

审查代码质量和最佳实践遵循情况

Step 5: 优化建议

提供性能优化和改进建议

Gotchas

1. 过度设计

避免在简单场景中使用复杂的设计模式

2. 性能忽视

不要忽视性能优化,特别是在生产环境中

3. 安全考虑

始终考虑安全性和数据保护

4. 测试覆盖

确保有足够的测试覆盖,特别是边界情况

5. 文档维护

保持文档与代码同步更新

评论

支持 Markdown