Flask 如何做错误处理?errorhandler 和 abort 有什么区别?
简化版
Flask 可以用 abort() 主动抛出 HTTP 错误,也可以用 @app.errorhandler 注册错误处理器,把异常或状态码转换成统一响应。abort(404) 是触发错误,errorhandler 是定义错误发生后如何返回。
详细版
from flask import abort, jsonify
@app.get("/users/<int:user_id>")
def get_user(user_id):
user = find_user(user_id)
if not user:
abort(404)
return jsonify(user)
@app.errorhandler(404)
def not_found(e):
return jsonify(error="not found"), 404
生产 API 通常要统一错误格式、记录 5xx 异常、区分业务错误和系统错误。面试要强调:不要把所有异常都吞成 200,也不要把内部堆栈暴露给用户。
完整版教学
一、为什么需要统一错误处理
接口调用方需要稳定错误格式。一个接口返回 HTML 错误页,一个返回 JSON,一个返回 200 但里面写 error,会让前端和调用方很痛苦。
{"code": "NOT_FOUND", "message": "user not found"}
统一错误处理让错误可读、可监控、可告警。
二、abort 做什么
abort() 用于主动终止请求并抛出 HTTPException。比如资源不存在、无权限、参数不合法。
if not user:
abort(404, description="user not found")
它不是返回响应,而是抛出异常,由 Flask 错误处理机制接管。
三、errorhandler 做什么
errorhandler 注册某类错误的处理逻辑。可以按状态码,也可以按异常类注册。
@app.errorhandler(ValueError)
def handle_value_error(e):
return jsonify(error=str(e)), 400
| 机制 | 作用 |
|---|---|
abort | 触发 HTTP 错误 |
errorhandler | 生成错误响应 |
register_error_handler | 动态注册处理器 |
四、蓝图错误处理
Blueprint 也可以注册 errorhandler,用于模块级错误处理。但 404 路由未匹配有时还没进入蓝图,可能由 app 级处理器处理。
bp = Blueprint("api", __name__)
@bp.errorhandler(400)
def bad_request(e):
...
大型项目通常 app 级统一兜底,蓝图级处理模块特殊错误。
五、5xx 错误如何处理
5xx 表示服务端错误,要记录堆栈和上下文,但响应给用户要克制。生产不能把 traceback 原样返回。
@app.errorhandler(Exception)
def handle_unexpected(e):
app.logger.exception("unexpected error")
return jsonify(error="internal server error"), 500
对用户隐藏内部细节,对日志保留足够上下文。
六、业务错误和 HTTP 错误
业务错误可以定义自定义异常,包含 code、message、status_code。错误处理器统一转换成 JSON。
class BusinessError(Exception):
status_code = 400
这样业务代码可以 raise BusinessError(...),不用每层手写 jsonify。
七、常见误区与追问
- 误区:所有错误都返回 200。 会破坏 HTTP 语义,监控也难做。
- 误区:errorhandler 里不需要日志。 5xx 必须记录堆栈和上下文。
- 误区:abort 和 return 一样。 abort 是抛异常触发错误处理。
- 追问:404 怎么统一 JSON? 注册 app 级 404 errorhandler。
- 追问:蓝图 404 为什么没生效? 路由匹配失败可能还没确定蓝图。
- 追问:如何处理参数错误? 抛业务异常或 abort 400,统一转换。
- 追问:生产能返回 traceback 吗? 不能,内部细节只进日志。
八、加强记忆
Flask 错误处理记成“abort 触发,errorhandler 接住,JSON 统一,日志留证”。4xx 是调用方问题,5xx 是服务端问题;用户看到克制信息,日志记录完整上下文。