为异步逻辑设计统一异常映射字典,以异常类为键绑定错误码、提示与动作,通过safe_await封装自动匹配(支持继承查找),返回标准化结构,并与业务异常基类协同实现分层处理,同时需防范task、线程等上下文逃逸问题。

为异步逻辑编写统一的异常映射字典,核心是把「异常类型」和「可读提示、错误码、处理动作」绑定起来,让所有 await 点都能复用同一套响应逻辑,避免重复判断和硬编码消息。
定义结构清晰的映射字典
字典键应为异常类(不是字符串),值为包含语义信息的字典或命名元组。例如:
- 用 类本身作键:如
ConnectionError: {"code": "NET_001", "msg": "网络连接失败,请检查网络", "level": "warn"} - 支持继承关系:若字典中未显式定义
TimeoutError,但定义了其父类OSError,可在查找时向上匹配(需手动实现 issubclass 判断) - 避免用字符串当键(如
"ConnectionError"),否则无法准确匹配子类或自定义异常
在 await 前后注入统一处理层
不能依赖 try/except 散落在每个 await 周围。推荐封装一个安全调用函数:
- 写一个
safe_await(coro, exc_map=EXC_MAP)工具函数,内部自动 try/catch 并查字典 - 捕获异常后,用
next((v for k, v in exc_map.items() if isinstance(exc, k)), DEFAULT_FALLBACK)查找最匹配项 - 返回标准化结构:如
{"success": False, "error": {...}},便于上层统一渲染或重试
与业务异常体系对齐
映射字典不是孤立存在,要和你的自定义异常基类协同工作:
- 所有业务异常(如
UserNotFound、InsufficientBalance)都应继承统一基类(如AppError) - 映射字典中优先覆盖具体业务异常类,再 fallback 到基类,最后才是系统异常(如
ValueError) - 业务异常实例可自带
.http_status或.retryable属性,映射字典可直接透传或增强这些字段
注意异步上下文中的特殊陷阱
映射字典再完善,也救不了逃逸出事件循环的异常:
-
asyncio.create_task()启动的任务,异常不会冒泡到父协程——必须在任务内部调用safe_await或加try/except - 信号处理器、后台线程、atexit 回调里的异步操作,完全不在事件循环管辖范围,需单独包裹
- 全局
sys.excepthook和loop.set_exception_handler()是最后防线,但它们看到的是原始异常,不经过你的映射字典——建议在这些钩子里记录原始异常,同时触发一次safe_await的 fallback 日志生成

















