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

时间:2015-01-03 22:15:48

标签: 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

然而,这种方法需要为每个错误代码提供一个显式的装饰器。有没有办法装饰我的(单个)http_error_handler函数,以便它处理所有 HTTP错误?

3 个答案:

答案 0 :(得分:14)

您可以将errorhandler装饰器与异常类而不是错误代码一起用作参数,如here所述。因此,您可以尝试例如

@application.errorhandler(HTTPException)
def http_error_handler(error):

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

@application.errorhandler(Exception)
def http_error_handler(error):

处理所有未捕获的异常

编辑:查看了烧瓶源代码,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):

应该达到你想要的效果。

由于看起来HTTPException具有每个HTTP错误代码的子类(请参阅here),设置'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

这可以完成我想要的一切,并且似乎可以处理HTTP和内部的所有错误。 if e.code < 400位用于重定向等烧瓶的默认行为(否则最终会出现错误500,这不是您想要的)

答案 1 :(得分: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)

但是将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) 一样。不要问我为什么,我没有找到答案。

所以我找到了一个非常好的替代解决方案:

carriage return

(在Github找到)

答案 2 :(得分:4)

您不是唯一的解决方法,一种解决方法是指定您正在捕获并绑定到 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

我知道并不理想和丑陋,但它会奏效,我希望其他人可以找到更好的解决方案。希望这会有所帮助。