python异常统一处理需三层配合:自定义业务异常类(如baseappexception及其子类)、中间件/装饰器全局捕获(fastapi用@exception_handler,flask用@errorhandler)、sys.excepthook兜底日志;同时联动日志与监控,确保错误可追溯、响应可控、信息脱敏。

Python中实现异常统一处理,核心是用 try-except 捕获 + 自定义异常类 + 全局钩子 三层配合,避免重复写 try,同时保证错误可追溯、响应可控。
定义业务异常基类,分类管理错误
不直接抛内置异常(如 ValueError),而是继承 Exception 自定义业务异常,便于统一识别和处理:
- 创建 BaseAppException 作为所有业务异常父类
- 按模块或场景派生子类,如 UserNotFoundException、InvalidParamError、ServiceUnavailableError
- 每个子类可自带 error_code、http_status、log_level 等属性,方便后续统一响应
示例:
class BaseAppException(Exception):
def __init__(self, message, code=500, status_code=500):
super().__init__(message)
self.message = message
self.code = code
self.status_code = status_code
<p>class UserNotFoundException(BaseAppException):
def <strong>init</strong>(self, user_id):
super().<strong>init</strong>(f"用户 {user_id} 不存在", code=1001, status_code=404)中间件/装饰器统一捕获(Web 场景)
在 Flask/FastAPI/Django 中,不推荐每个路由都写 try-except。应通过中间件或异常处理器接管:
立即学习“Python免费学习笔记(深入)”;
-
FastAPI:用
@app.exception_handler(BaseAppException)注册处理器,返回标准化 JSON 响应 -
Flask:用
@app.errorhandler(BaseAppException)或自定义装饰器包装视图函数 - 通用装饰器:对非 Web 函数也可用 @handle_exceptions 包裹,自动捕获 BaseAppException 并记录日志
关键点:捕获后不要裸抛,要记录 traceback(用 logging.exception),并返回结构化错误体(如 {"code": 1001, "msg": "用户不存在"})。
设置 sys.excepthook 处理未捕获异常
主线程中未被 try 捕获的异常,会触发 Python 默认异常处理器。用 sys.excepthook 替换它,实现兜底日志和退出前清理:
- 重写 hook 函数,打印完整 traceback、记录到文件、上报监控系统(如 Sentry)
- 注意:该 hook 不捕获线程内异常,多线程需配合 threading.excepthook(Python 3.8+)
- 避免在 hook 中 raise 新异常,否则程序可能静默退出
示例:
import sys
import logging
<p>def global_exception_handler(exc_type, exc_value, exc_traceback):
logging.critical("未捕获异常", exc_info=(exc_type, exc_value, exc_traceback))</p><h1>可选:发送告警、保存 dump、清理资源</h1><p>sys.excepthook = global_exception_handler日志 + 监控联动,让异常真正“可见”
统一处理不是为了吞掉错误,而是为了更准确定位问题:
- 每条异常日志必须包含 request_id(Web)、trace_id(分布式链路)、发生位置(__file__:line)
- 对高频异常(如数据库连接失败)做计数告警,避免“日志里有但没人看”
- 在异常处理器中调用 metrics.increment("error.count", tags={"type": exc.__class__.__name__})
不复杂但容易忽略:异常信息要脱敏(不打密码、token、身份证号),日志级别设为 ERROR 或 CRITICAL,但调试时可临时开启 DEBUG 级别 traceback。










