关于 python-anti-patterns
python-anti-patterns 是供 Python 开发者审查代码的反模式清单,涵盖基础设施、架构、错误处理、资源、类型和测试等方面。它通过问题示例、改进方向和检查项,帮助在合并前审查或重构时发现常见问题。
主要功能
- 01检查重试与配置管理问题
- 02识别架构和错误处理反模式
- 03检查资源使用与异步阻塞
- 04涵盖类型标注和测试边界
适用场景
- 01合并前审查 Python 代码
- 02排查可能由不良实践导致的问题
- 03重构遗留代码并建立团队规范
- 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.txtagents/openai.yamlexamples/advanced-usage.mdbasic-usage.mdintegration.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. 文档维护
保持文档与代码同步更新