@app.errorhandler仅捕获HTTPException及其子类异常,不捕获ValueError等普通异常;需用@app.errorhandler(Exception)捕获所有未处理异常,但要注意优先级和自定义异常设计。

Flask 中 @app.errorhandler 能捕获哪些异常?
它只捕获由 Flask 主动抛出的 HTTP 异常(如 NotFound、BadRequest)和未被视图函数捕获的、继承自 HTTPException 的异常。普通 ValueError、KeyError 或数据库连接失败这类非 HTTP 异常,默认不会进这里。
常见误判:写了个 @app.errorhandler(500) 就以为能兜住所有崩溃,结果 ZeroDivisionError 仍会返回默认 500 页面或直接爆 traceback。
- 要捕获所有未处理异常,必须额外注册
@app.errorhandler(Exception) -
@app.errorhandler(500)和@app.errorhandler(Exception)不冲突,但后者优先级更高(更宽泛) - 若同时注册两者,
Exception处理器会吞掉所有非 HTTP 异常,包括你本想单独处理的DatabaseError
如何区分业务异常与系统异常并分别响应?
硬编码一堆 if isinstance(e, XXX) 不可持续。推荐在应用启动时统一注册细粒度处理器,并让业务层主动抛出自定义异常。
例如定义 class ValidationError(Exception) 和 class ExternalServiceError(Exception),再分别注册:
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
立即学习“Python免费学习笔记(深入)”;
@app.errorhandler(ValidationError)
def handle_validation_error(e):
return {"error": "validation_failed", "message": str(e)}, 400
@app.errorhandler(ExternalServiceError)
def handle_service_error(e):
return {"error": "service_unavailable", "message": "Upstream failed"}, 503
- 自定义异常类建议继承
Exception而非HTTPException,避免被 Flask 自动转成 HTTP 响应码 - 不要在自定义异常里硬编码状态码,状态码由 handler 决定,保持关注点分离
- 确保异常类在所有可能抛出它的模块中都能被 import 到(比如统一放在
exceptions.py)
为什么 JSON 错误响应在调试模式下不生效?
Flask 默认在 DEBUG=True 时禁用所有 @app.errorhandler,直接显示 Werkzeug 调试页面。这是故意设计,不是 bug。
- 本地开发时想看 JSON 错误,可临时设
app.config['TRAP_HTTP_EXCEPTIONS'] = True - 但更稳妥的做法是:用
app.config['PROPAGATE_EXCEPTIONS'] = False配合全局Exceptionhandler,它在 DEBUG 模式下依然有效 - 生产环境务必关掉
DEBUG,否则 traceback 可能泄露敏感路径或变量名
日志记录和 Sentry 上报容易漏掉什么?
只在 error handler 里写 logger.exception("Unhandled error") 是不够的——如果 handler 本身出错(比如 JSON 序列化失败),错误就彻底丢失了。
- 在
@app.errorhandler(Exception)开头加logger.exception,且确保 logger 配置了文件/远程输出,不依赖 console - 上报 Sentry 时,用
sentry_sdk.capture_exception(),不要只传字符串消息 - 注意:Werkzeug 的
BadRequest等 HTTP 异常默认不触发logger.exception,需为它们也单独加日志逻辑
最常被忽略的是异步任务(如 Celery)或后台线程里的异常——它们完全脱离 Flask 请求上下文,@app.errorhandler 对它们无效,必须单独处理。

















