Flask 中应使用 app.errorhandler() 分层注册异常处理器,显式处理 NotFound 等 HTTP 异常,用 @app.errorhandler(500) 捕获未匹配的服务器错误,避免注册 Exception;Django 优先选 process_exception 中间件统一记录异常;FastAPI 异常处理器建议带 Request 参数并按 specificity 顺序注册;错误响应须统一字段、分离日志与敏感信息。

Flask 中如何设置全局异常处理器
Flask 本身不自动捕获未处理的异常并返回友好响应,直接抛出会导致 500 页面暴露堆栈——这在生产环境必须禁用。app.errorhandler() 是唯一可靠方式,它按异常类型注册处理器,优先级高于 try/except 块外的通用兜底。
常见错误是只注册 Exception,结果覆盖了 Flask 内置的 404/405 处理逻辑。正确做法是分层注册:
- 显式注册
NotFound、MethodNotAllowed等 HTTP 异常,避免干扰默认行为 - 用
@app.errorhandler(500)捕获所有未被更具体处理器匹配的服务器错误 - 避免注册
@app.errorhandler(Exception),它会吞掉系统级异常(如内存溢出),导致进程静默崩溃
示例中返回 JSON 而非 HTML,是因为 Web API 场景下客户端无法解析模板错误页:
@app.errorhandler(500)
def internal_error(error):
return {"error": "Internal server error", "code": 500}, 500
Django 的 middleware vs handler500 怎么选
Django 提供两条路径:全局中间件(process_exception)和视图层兜底(handler500)。前者能拦截所有视图异常,包括中间件自身抛出的;后者仅在视图函数内未捕获异常时触发,且无法访问请求上下文中的中间件状态。
关键区别在于执行时机和可访问数据:
立即学习“Python免费学习笔记(深入)”;
-
process_exception在响应生成前运行,可读取request和原始exception对象,适合做日志、审计或动态降级 -
handler500是纯视图函数,接收的是request对象(无异常实例),只能返回 HttpResponse,无法根据异常类型差异化响应 - 若需统一记录异常堆栈,必须用中间件;若只需替换 500 页面模板,
handler500更轻量
注意:Django 3.2+ 默认关闭 DEBUG=False 下的详细错误页,但未配置 handler500 时仍会返回空响应体,务必显式定义。
FastAPI 的 ExceptionHandler 必须用 Request 参数吗
不是必须,但强烈建议。FastAPI 的异常处理器签名支持两种形式:def handler(request: Request, exc: Exception) 或 def handler(exc: Exception)。省略 Request 会导致无法获取客户端 IP、请求头、路径等关键上下文,而这些信息对错误分类和告警至关重要。
另一个易错点是注册顺序:FastAPI 按注册顺序匹配处理器,更具体的异常类(如 HTTPException)必须在通用 Exception 之前注册,否则会被后者提前截获。
- 自定义异常应继承
HTTPException,而非Exception,确保能被 FastAPI 正确识别状态码 - 使用
app.add_exception_handler()注册时,传入的异常类必须是实际抛出的类型,不能是父类别名(如用ValueError捕获ValidationError会失败) - 异步处理器需用
async def,否则事件循环会阻塞
跨框架通用的错误响应结构设计要点
无论用哪个框架,错误响应体格式混乱是前端联调的最大痛点。核心原则是:字段命名一致、状态码可信、错误信息不泄露内部细节。
必须规避的实践:
- 混用
message/detail/error字段名,前端要写三套解析逻辑 - 把 Python traceback 当
message直接返回,等于向攻击者暴露代码路径和依赖版本 - 对 400 类错误也返回 500 状态码,导致前端无法区分是用户输错还是服务挂了
推荐最小字段集:{"code": "VALIDATION_ERROR", "message": "Email format invalid", "field": "email"}。其中 code 是机器可读的错误码(非 HTTP 状态码),message 是用户友好的提示,field 仅在表单校验时存在。HTTP 状态码严格对应语义:400 用于客户端错误,500 仅限未预期的服务端崩溃。
最常被忽略的是日志与响应的分离:响应体里删掉敏感信息,但日志里必须保留完整 exc_info —— 否则线上问题根本无法复现。


















