flask异常处理

1. flask exception

在view函数中,如果需要中断request,可以使用abort(500)或者直接raise exception。当然我们还需要返回一个出错信息给前端,所以需要定制一下ErrorHandler。
一般只需要两个handler即可,一个是404错误,一个是500一类的服务器端错误。当然也可以自定义错误。

1.1. abort/errorhandler

abort:flask中异常处理语句,功能类似于raise语句;触发abort后会中止视力方法,返回分发函数;abort参数需为http状态码的子集。
errorhandler:装饰器,注册异常处理函数,配合abort函数使用,根据状态码匹配,返回Response() 实例或者(string, status_code)。

from werkzeug.exceptions import abort
@app.route('/abort')
def view_abort():
    abort(405) # 请求中断,返回状态码405

@app.errorhandler(405) # 处理中断,返回响应体
def err_handle(e):
    return '错误404' + str(e), 405
    # return Response('错误404' + str(e), 405) # 与上一行效果相同

1.3. 蓝图异常处理

蓝图也可以注册异常处理方法,可以注册蓝图级/全局级异常处理函数(仅装饰器方法名不同)。
具体见下方案例,不过不建议在蓝图中注册全局级异常处理函数。

# 非全局
@blue_t.errorhandler(405)
def err_405(e):
    print('err_405')
    return 'error 405 from blueprint blue_t'

# app_errorhandler()是全局的
@blue_t.app_errorhandler(405)
def err_404(e):
    return 'blueprint error_405'
    #return render_template('error/404.html')

案例

生产环境下一般将大部分异常隐藏,只返回500到前端。
下例即是将错误日志写入文件,前端返回500

from flask import jsonify, render_template
from flask import abort, current_app

from werkzeug.http import HTTP_STATUS_CODES

# 异常处理
def register_errors(app):
    from werkzeug.exceptions import HTTPException
    @app.errorhandler(404)
    def page_not_found(error):
        return render_template('error/404.html'), 404

    @app.errorhandler(405)
    def err_405(e):
        # print('main:err_405')
        return '错误405: ' + str(e), 405

    @app.errorhandler(HTTPException) # 处理除上述异常以外的所有异常
    def err_all(error):
        current_app.logger_main.error(error, exc_info=True)
        return Response(r'服务器错误', 500)

2. 总结

关于abort/errorhandler
flask在full_dispatch_request中处理请求,如果使用abort即为抛出异常,
接下来执行rv = self.handle_user_exception(e)
它会去注册的异常处理函数中根据e.code(abort的参数)匹配,并且优先在蓝图的异常处理函数中进行匹配
无论如何,最后的结果一定是Response() 实例或者(string, status_code)。
如果愿意的话,也可以直接在视图中 return Response('error 500', 500)

顶层app中的异常处理集中到函数中然后调用。
尽量不要在蓝图中声明全局异常处理。

对于异常可以由server仅返回状态码,nginx返回静态网页,以节约服务器资源。