flask 全局异常处理

场景描述

这几天刚接到的需求:padlepadle + flask + docker。web功能不复杂,但该有的日志、异常捕获这些都还是不能少的。之前异常捕获老用 try-except,这次想试试全局异常捕获,花了几个小时研究了下。发现关键的就几行代码。

全局异常捕获

异常分为客户端异常和服务端异常,flask 中的异常处理分为三步走:异常注册、异常触发、异常处理。先看段代码,边测边写。

from flask import *
from paddlenlp import Taskflow
from werkzeug.exceptions import HTTPException

app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False

@app.errorhandler(Exception)
def handle_500_exception(e):
    # pass through HTTP errors
    if isinstance(e, HTTPException):
        return e

    # now you're handling non-HTTP exceptions only
    return render_template("500_generic.html", e=e), 500

@app.errorhandler(HTTPException)
def handle_exception(e):
    response = e.get_response()
    response.data = json.dumps({
    
    
        "code": e.code,
        "name": e.name,
        "description": e.description,
    })
    response.content_type = "application/json"
    return response

class RequestParamException(HTTPException):
    code = 400

def handle_param_exception(e):
    response = e.get_response()
    response.data = json.dumps({
    
    
        "code": e.code,
        "name": "子类:RequestParamException 处理的异常。",
        "description": e.description,
    })
    response.content_type = "application/json"
    return response

@app.route('/add_user', methods=['POST'])
def add_documents():
    data = request.get_json()
    user = data['user']
    if user is None or len(user) <= 0:
        raise RequestParamException(description="user 不能为 None 或 ''。")
    return {
    
    "user": user}, 201


if __name__ == '__main__':
    app.register_error_handler(RequestParamException, handle_param_exception)
    app.run(debug=True)

正常请求

curl --request POST \
  --url http://127.0.0.1:5000/add_user \
  --header 'Content-Type: application/json' \
  --data '{"user":"diego"}'
#----
{
    
    
  "user": "diego"
}

客户端全局异常捕获,@app.errorhandler 向 flask 注册了 HTTPException 异常以及该异常的处理方法 handle_exception(e)。客户端的所有请求他都囊括了,404、405、400 等等,一旦这些异常触发,都会执行到 handle_exception(e) 方法中,最后将异常信息返回给客户端。至于方法里面的具体内容,自己看吧。

@app.errorhandler(HTTPException)
def handle_exception(e):
    response = e.get_response()
    response.data = json.dumps({
    
    
        "code": e.code,
        "name": e.name,
        "description": e.description,
    })
    response.content_type = "application/json"
    return response

触发 404 异常

curl --request POST \
  --url http://127.0.0.1:5000/add_user2 \
  --header 'Content-Type: application/json' \
  --data '{"user":"diego"}' | jq
{
    
    
  "code": 404,
  "description": "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.",
  "name": "Not Found"
}

触发 405 异常

curl --request GET \
  --url http://127.0.0.1:5000/add_user \
  --header 'Content-Type: application/json' \
  --data '{"user":"diego"}' | jq
{
    
    
  "code": 405,
  "description": "The method is not allowed for the requested URL.",
  "name": "Method Not Allowed"
}

自定义异常

还可以在 HTTPException 基础上自定义异常信息,比如在参数不符合要求,抛出异常。当子类异常与父类异常同时存在时,优先让子类异常捕获。

## 定义异常类
class RequestParamException(HTTPException):
    code = 400
## 定义异常处理方法
def handle_param_exception(e):
    response = e.get_response()
    response.data = json.dumps({
    
    
        "code": e.code,
        "name": "子类:RequestParamException 处理的异常。",
        "description": e.description,
    })
    response.content_type = "application/json"
    return response  

注册异常除了 @app.errorhandler 以外,还有另外的一种方式:

app.register_error_handler(RequestParamException, handle_param_exception)

测试参数异常

curl --request POST \
  --url http://127.0.0.1:5000/add_user \
  --header 'Content-Type: application/json' \
  --data '{"user":""}' | jq
{
    
    
  "code": 400,
  "description": "user 不能为 None 或 ''。",
  "name": "子类:RequestParamException 处理的异常。"
}

服务端异常

@app.errorhandler(Exception)
def handle_500_exception(e):
    # pass through HTTP errors
    if isinstance(e, HTTPException):
        return e
    # now you're handling non-HTTP exceptions only
    return render_template("500_generic.html", e=e), 500

服务端异常 HTTPException 是捕获不了的,只能单独处理。

处理特定状态码的异常

@app.errorhandler(406)
def handle_exception(e):
    response = e.get_response()
    response.data = json.dumps({
    
    
        "code": e.code,
        "name": e.name,
        "description": e.description,
    })
    response.content_type = "application/json"
    return response

猜你喜欢

转载自blog.csdn.net/yy_diego/article/details/127775426
今日推荐