如何为Flask中的所有HTTP错误实现自定义错误处理程序?

oro*_*ome 8 python error-handling flask python-decorators

在我的Flask应用程序中,我可以通过errorhandler为每个错误代码添加装饰器来轻松扩展由单个自定义错误处理程序处理的错误列表,如同

@application.errorhandler(404)
@application.errorhandler(401)
@application.errorhandler(500)
def http_error_handler(error):
    return flask.render_template('error.html', error=error), error.code
Run Code Online (Sandbox Code Playgroud)

但是,此方法需要为每个错误代码使用显式装饰器.有没有办法装饰我的(单个)http_error_handler函数,以便它处理所有 HTTP错误?

McD*_*fin 15

您可以使用errorhandler装饰例外类,而不是错误代码作为参数,如描述在这里.因此你可以试试

@application.errorhandler(HTTPException)
def http_error_handler(error):
Run Code Online (Sandbox Code Playgroud)

处理所有HTTP错误(可能意味着所有HTTP错误代码),甚至

@application.errorhandler(Exception)
def http_error_handler(error):
Run Code Online (Sandbox Code Playgroud)

处理所有未捕获的异常

编辑:看过烧瓶源代码后,app config中有一个'TRAP_HTTP_EXCEPTIONS'标志,您可以更改(例如app.config['TRAP_HTTP_EXCEPTIONS']=True).

(粗略地)当这个标志为false时,作为HTTPException实例的异常由你装饰的函数处理,errorhandler(n)其中n是HTTP错误代码; 当此标志为true时,所有HTTPException实例都由您装饰的函数处理errorhandler(c),其中c是异常类.

这样做

app.config['TRAP_HTTP_EXCEPTIONS']=True

@application.errorhandler(Exception)
def http_error_handler(error):
Run Code Online (Sandbox Code Playgroud)

应该达到你想要的.

由于看起来HTTPException具有每个HTTP错误代码的子类(请参见此处),设置'TRAP_HTTP_EXCEPTIONS'并使用异常类装饰错误处理程序而不是错误代码看起来像是一种严格更灵活的处理方式.

作为参考,我的烧瓶错误处理现在看起来像:

app.config['TRAP_HTTP_EXCEPTIONS']=True

@app.errorhandler(Exception)
def handle_error(e):
    try:
        if e.code < 400:
            return flask.Response.force_type(e, flask.request.environ)
        elif e.code == 404:
            return make_error_page("Page Not Found", "The page you're looking for was not found"), 404
        raise e
    except:
        return make_error_page("Error", "Something went wrong"), 500
Run Code Online (Sandbox Code Playgroud)

这样做我想要的一切,似乎处理HTTP和内部的所有错误.这个if e.code < 400位是使用flask的重定向等默认行为(否则那些最终为错误500,这不是你想要的)


Anz*_*zel 5

您不是唯一的一个,一种解决方法是指定要捕获并绑定到application.error_handler_spec的http错误代码的列表,并删除装饰器,如下所示:

def http_error_handler(error):
    return flask.render_template('error.html', error=error), error.code

for error in (401, 404, 500): # or with other http code you consider as error
    application.error_handler_spec[None][error] = http_error_handler
Run Code Online (Sandbox Code Playgroud)

我知道这并不理想且丑陋,但它会起作用,并且我希望其他人可以提供更好的解决方案。希望这可以帮助。


Cyr*_* N. 5

对我来说,以下代码片段无效:

@app.errorhandler(HTTPException)
def _handle_http_exception(e):
    return make_response(render_template("errors/http_exception.html", code=e.code, description=e.description), e.code)
Run Code Online (Sandbox Code Playgroud)

但是改成HTTPException真正的,像NotFound,是行得通的。不要问我为什么,我没有找到答案。

因此,我找到了一种效果很好的替代解决方案:

from werkzeug.exceptions import default_exceptions

def _handle_http_exception(e):
    return make_response(render_template("errors/http_exception.html", code=e.code, description=e.description), e.code)

for code in default_exceptions:
    app.errorhandler(code)(_handle_http_exception)
Run Code Online (Sandbox Code Playgroud)

(在Github上找到)