任何异常的全局错误处理程序

问题描述 投票:35回答:6

有没有办法添加一个全局的catch-all错误处理程序,我可以在其中更改对通用JSON响应的响应?

我不能使用got_request_exception信号,因为它不允许修改响应(http://flask.pocoo.org/docs/0.10/signals/)。

相反,所有信号处理程序都以未定义的顺序执行,不会修改任何数据。

我宁愿不包装app.handle_exception函数,因为它感觉像内部API。我想我的事情是这样的:

 @app.errorhandler()
 def handle_global_error(e):
     return "Global error"

请注意,errorhandler不接受任何参数,这意味着它将捕获所有没有附加特定错误处理程序的异常/状态代码。我知道我可以使用errorhandler(500)errorhandler(Exception)来捕获异常,但是如果我以abort(409)为例,它仍会返回HTML响应。

python error-handling flask http-error
6个回答
45
投票

你可以使用@app.errorhandler(Exception)

Demo(HTTPException检查确保保留状态代码):

from flask import Flask, abort, jsonify
from werkzeug.exceptions import HTTPException

app = Flask('test')

@app.errorhandler(Exception)
def handle_error(e):
    code = 500
    if isinstance(e, HTTPException):
        code = e.code
    return jsonify(error=str(e)), code

@app.route('/')
def index():
    abort(409)

app.run(port=1234)

输出:

$ http get http://127.0.0.1:1234/
HTTP/1.0 409 CONFLICT
Content-Length: 31
Content-Type: application/json
Date: Sun, 29 Mar 2015 17:06:54 GMT
Server: Werkzeug/0.10.1 Python/3.4.3

{
    "error": "409: Conflict"
}

$ http get http://127.0.0.1:1234/notfound
HTTP/1.0 404 NOT FOUND
Content-Length: 32
Content-Type: application/json
Date: Sun, 29 Mar 2015 17:06:58 GMT
Server: Werkzeug/0.10.1 Python/3.4.3

{
    "error": "404: Not Found"
}

如果您还想覆盖Flask中的默认HTML异常(以便它们也返回JSON),请在app.run之前添加以下内容:

from werkzeug.exceptions import default_exceptions
for ex in default_exceptions:
    app.register_error_handler(ex, handle_error)

对于较旧的Flask版本(<= 0.10.1,即此时的任何非git / master版本),将以下代码添加到应用程序以明确注册HTTP错误:

from werkzeug import HTTP_STATUS_CODES
for code in HTTP_STATUS_CODES:
    app.register_error_handler(code, handle_error)

10
投票

这是Flask 0.12兼容,并且是一个非常好的解决方案(它允许用JSON或任何其他格式呈现错误)

from functools import wraps
from flask import Flask, redirect, jsonify
app = Flask(__name__)

def get_http_exception_handler(app):
    """Overrides the default http exception handler to return JSON."""
    handle_http_exception = app.handle_http_exception
    @wraps(handle_http_exception)
    def ret_val(exception):
        exc = handle_http_exception(exception)    
        return jsonify({'code':exc.code, 'message':exc.description}), exc.code
    return ret_val

# Override the HTTP exception handler.
app.handle_http_exception = get_http_exception_handler(app)

https://github.com/pallets/flask/issues/671#issuecomment-12746738


6
投票

远非优雅,但以下工作将HTTPException的所有子类绑定到单个错误处理程序:

from flask import jsonify
from werkzeug.exceptions import HTTPException

def handle_error(error):
    code = 500
    if isinstance(error, HTTPException):
        code = error.code
    return jsonify(error='error', code=code)

for cls in HTTPException.__subclasses__():
    app.register_error_handler(cls, handle_error)

2
投票

在Flask> = 0.12中实现此方法的更简洁方法是为每个Werkzeug异常显式注册处理程序:

from flask import jsonify
from werkzeug.exceptions import HTTPException, default_exceptions

app = Flask('test')

def handle_error(error):
    code = 500
    if isinstance(error, HTTPException):
        code = error.code
    return jsonify(error='error', code=code)

for exc in default_exceptions:
    app.register_error_handler(exc, handle_error)

0
投票

如果异常不起作用,您可以尝试app.register_error_handler(或以非装饰方式使用app.errorhandler)

资料来源:https://github.com/pallets/flask/issues/1837


0
投票

基于Plain (non-HTML) error pages in REST api

我想在不改变任何代码的情况下返回json,所以我在代码的顶部添加了以下内容

@app.errorhandler(500)
def error_500(exception):
    return jsonify({"error": str(exception)}), 500, {'Content-Type': 'application/json'}

@app.errorhandler(400)
def error_400(exception):
    return jsonify({"error": str(exception)}), 400, {'Content-Type': 'application/json'}
© www.soinside.com 2019 - 2024. All rights reserved.