plugins/languages/python/skills/error/SKILL.md
Python 异常处理与结构化日志规范。涵盖自定义异常层次、except* / ExceptionGroup、structlog 结构化日志、Context Manager 资源管理、错误传播策略。在设计异常类型、配置日志、排查异常、写资源清理代码时使用。也触发于"异常处理"、"自定义异常"、"structlog"、"logging"、"try/except"。
npx skillsauth add lazygophers/ccplugin python-errorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
每个项目定义一个根异常, 业务异常都继承自它:
class AppError(Exception):
"""应用根异常。所有业务异常继承自此。"""
class ValidationError(AppError):
def __init__(self, field: str, message: str) -> None:
super().__init__(f"{field}: {message}")
self.field = field
class NotFoundError(AppError):
def __init__(self, resource: str, id: int | str) -> None:
super().__init__(f"{resource} #{id} not found")
self.resource = resource
self.id = id
class ExternalServiceError(AppError):
"""外部服务调用失败 (可重试)。"""
好处:
except AppError 捕获全部业务异常except Exception 仅用于框架边界 (HTTP handler, async task 顶层)except: 或 except Exception: (除非顶层 handler)raise NewError(...) from e (用 from, 不要 raise NewError(str(e)))# good
try:
user = await db.get_user(uid)
except DatabaseConnectionError as e:
log.error("db_unavailable", user_id=uid, exc_info=True)
raise ExternalServiceError("user-service") from e
# bad - 吞异常
try:
user = await db.get_user(uid)
except Exception:
user = None # 静默失败, 上层无法察觉
并发任务 (TaskGroup, asyncio.gather) 会抛 ExceptionGroup, 必须用 except*:
async with asyncio.TaskGroup() as tg:
tg.create_task(fetch_a())
tg.create_task(fetch_b())
# 若两个都失败, raise ExceptionGroup([err_a, err_b])
try:
await run_pipeline()
except* ValidationError as eg:
for e in eg.exceptions:
log.warning("validation_failed", error=str(e))
except* ExternalServiceError as eg:
raise # 让上层重试
不要用 print 调试, 不要用裸 logging 拼字符串。用 structlog 输出 JSON:
import structlog
structlog.configure(
processors=[
structlog.contextvars.merge_contextvars,
structlog.processors.add_log_level,
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.JSONRenderer(),
],
)
log = structlog.get_logger()
# 业务代码: 键值对而非 f-string
log.info("user_created", user_id=user.id, email=user.email)
log.error("payment_failed", order_id=oid, amount=amt, exc_info=True)
关键约定:
snake_case, 动词过去式 (user_created 而非 creating user)structlog.contextvars.bind_contextvars(request_id=...) 注入, 不在每行手传exc_info=True 自动附带 traceback老项目仍用 stdlib logging 也可, 但配置 dictConfig + JSON formatter:
import logging
logger = logging.getLogger(__name__) # 不要 logging.getLogger() 拿 root
logger.error("payment failed for order=%s amount=%s", oid, amt, exc_info=True)
不要用 f-string 拼日志消息 (字符串会先求值, 即使日志级别被过滤掉)。用 %s 占位符。
任何需要清理的资源都用 with / async with, 不要手写 try/finally:
# sync
from contextlib import contextmanager
@contextmanager
def transaction(db):
tx = db.begin()
try:
yield tx
tx.commit()
except Exception:
tx.rollback()
raise
with transaction(db) as tx:
tx.execute(...)
# async
async with httpx.AsyncClient() as client:
resp = await client.get(url)
多资源用 contextlib.ExitStack / AsyncExitStack, 不要嵌套 with。
FastAPI / Litestar 等 Web 框架边界, 把业务异常转 HTTP 响应:
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
app = FastAPI()
@app.exception_handler(NotFoundError)
async def not_found_handler(req: Request, exc: NotFoundError) -> JSONResponse:
return JSONResponse(status_code=404, content={
"error": "not_found",
"resource": exc.resource,
"id": exc.id,
})
业务代码只 raise 领域异常, handler 统一翻译。不要在业务函数里 raise HTTPException。
except: pass / except Exception: pass (静默失败)raise Exception("...") (用具体异常类)logger.error(f"failed: {e}") (丢 traceback, 用 exc_info=True)print(...) 调试代码留在生产getLogger(__name__), 应用层配置)raise X from e)tools
UI/UX 与布局设计——做界面布局/结构/导航/组件/交互的设计决策。触发:做UI/UX/布局/排版/导航/组件/交互/栅格/响应式/图表选型/字体配对。按媒介路由 HTML/Web、原生 App(iOS/Android/桌面)、CLI、TUI。需后端动态系统不适用;配色/主题/色板走姊妹 skill design-color。
tools
主题与配色设计——做颜色搭配/调色板/主题/品牌色阶/暗模式的设计决策。触发:选配色/调色/主题/色板/品牌色/暗模式/对比度/色盲/UI风格。按媒介路由 HTML/Web(CSS变量)、原生App(平台token)、CLI(ANSI)、TUI(真彩/256/16降级)。保证可访问性(对比度/色盲安全)。需后端动态系统不适用;UI/UX 布局/组件/交互走姊妹 skill design-uiux。
tools
跨任意组件(plugin/skill/agent/command)的验证驱动优化循环纪律 skill。当用户要优化某个已有组件却无明确方向、或要防止改了反而更差(自评乐观偏差 / 多维同改归因失效 / 为凑分加废话膨胀)、或要把一套通用「评分→单变量改→改后验证严格更好才留否则回滚→触顶停」的纪律套到任意组件上时使用。管优化过程本身的纪律(validation gate / ratchet / 独立验证 / 触顶停),不评单组件深度(交 skill-dev),不查插件接线(交 plugin-dev)。仅手动 /optimize-any 触发。
data-ai
两层规则记忆 (基于 .skein/spec)。planning 时 recall 召回相关规则、task finish 后 sediment 沉淀学习 + prune 自动精简过期/重复/断链规则。core 常驻硬规 + recall 按需召回, 经判定门自动写盘 (不逐次问用户)。产出 .skein/spec 下 core/recall 规则文件 + index。另支持空仓 bootstrap 播种规则基线、记忆大面积失效 (大重构/换栈) 时 reconstruct 可逆归档后按项目类型分型重建、maintain 手动体检 (超预算/stale/断链/重复/废弃, --apply 自动修复)、auto-fix (Stop hook 写 .pending-fix 标记 → main 派 skein-specer bg 跑 maintain --apply 全自动修, 断链只报告)。