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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29332056/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 04:25:26  来源:igfitidea点击:

Global error handler for any exception

pythonerror-handlingflaskhttp-error

提问by joscarsson

Is there a way to add a global catch-all error handler in which I can change the response to a generic JSON response?

有没有办法添加全局捕获所有错误处理程序,我可以在其中将响应更改为通用 JSON 响应?

I can't use the got_request_exceptionsignal, as it is not allowed to modify the response (http://flask.pocoo.org/docs/0.10/signals/).

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

In contrast all signal handlers are executed in undefined order and do not modify any data.

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

I would prefer to not wrap the app.handle_exceptionfunction as that feels like internal API. I guess I'm after something like:

我宁愿不包装app.handle_exception函数,因为这感觉像是内部 API。我想我在追求类似的东西:

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

Note the errorhandlerdoes not take any parameters, meaning it would catch all exceptions/status codes which does not have a specific error handler attached to them. I know I can use errorhandler(500)or errorhandler(Exception)to catch exceptions, but if I do abort(409)for example, it will still return a HTML response.

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

采纳答案by ThiefMaster

You can use @app.errorhandler(Exception):

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

Demo (the HTTPException check ensures that the status code is preserved):

演示(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)

Output:

输出:

$ 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"
}

If you also want to override the default HTML exceptions from Flask (so that they also return JSON), add the following before app.run:

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

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

For older Flask versions (<=0.10.1, i.e. any non-git/master version at the moment), add the following code to your application to register the HTTP errors explicitly:

对于较旧的 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)

回答by bwind

Far from elegant, but the following works for tying all subclasses of HTTPExceptionto a single error handler:

远非优雅,但以下适用于将所有子类绑定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)

回答by lol

This is Flask 0.12 compatible, and a very good solution to the problem (it allows one to render errors in JSON or any other format)

这是 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

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

回答by Suresh Ganta

If the Exceptions doesn't work, you may try app.register_error_handler(or use app.errorhandlerin a non-decorator way)

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

Source: https://github.com/pallets/flask/issues/1837

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

回答by nfvs

A cleaner way to implement this in Flask >=0.12 would be to explicitly register the handler for every Werkzeug exception:

在 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)

回答by julianalimin

Based on Plain (non-HTML) error pages in REST api

基于 REST api 中的普通(非 HTML)错误页面

I wanted to return json without changing any of my code at all, so I just added the following on the top of my code

我想在不更改任何代码的情况下返回 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'}