PS 最近才入坑flask,之前一直以pyqt5为主,在使用flask的过程中碰到了居多的难题和坑,记录一下,笔记有点杂乱,能保证看懂就行。

自定义异常反馈格式

基本上网上的一些教程都有,以下代码不做过多说明

# error_types.py
import json

from flask import request
from werkzeug.exceptions import HTTPException


class APIException(HTTPException):
    """API错误基类"""
    code = 500
    msg = 'Sorry, we made a mistake Σ(っ °Д °;)っ'
    error_code = 999

    def __init__(self, msg=None, code=None, error_code=None, headers=None):
        if code:
            self.code = code
        if msg:
            self.msg = msg
        if error_code:
            self.error_code = error_code
        super(APIException, self).__init__(msg, None)

    @staticmethod
    def get_error_url():
        """获取出错路由和请求方式"""
        method = request.method
        full_path = str(request.full_path)
        main_path = full_path.split('?')[0]
        res = method + ' ' + main_path
        return res

    def get_body(self, environ=None, scope=None):
        """异常返回信息"""
        body = dict(
            msg=self.msg,
            error_code=self.error_code,
            request=self.get_error_url()
        )
        text = json.dumps(body)
        return text

    def get_headers(self, environ=None, scope=None):
        """异常返回格式"""
        return [("Content-Type", "application/json")]


class Success(APIException):
    """操作成功"""
    code = 201
    msg = 'Ok'
    error_code = 0


class ServerError(APIException):
    """服务器错误/未知错误"""
    code = 500
    msg = 'Sorry, we made a mistake Σ(っ °Д °;)っ'
    error_code = 9999

全局异常捕获

网上也能搜到很多,需要注意:errorhandler和app_errorhandler的使用

# errors.py
from flask import Blueprint
from werkzeug.exceptions import HTTPException

from applications.libs.error_type import APIException, ServerError

exception_bp = Blueprint("error", __name__)

"""
如果用的工厂模式创建app,需要使用app_errorhandler捕获全局异常
如果是常规的 app = Flask(__name__), 使用errorhandler即可捕获全局异常
PS 网上说的,没有一一测试过
"""
@exception_bp.app_errorhandler(Exception)
def framework_error(e):
    if isinstance(e, APIException):
    	# 自定义好的异常
        return e
    elif isinstance(e, HTTPException):
        code = e.code
        msg = e.description
        error_code = 1001  # 已知异常状态码, 包含常规的404、405等等已经被flask定义好的异常,一可以根据需求进行细分
        return APIException(msg=msg, code=code, error_code=error_code)
    else:
        return ServerError()

坑来了:使用flask-restful

"""
当没有使用flask-restful时
是通过直接使用app.route()来反馈视图函数的内容时,发现所有的异常都会通过 framework_error,反馈格式也是固定的
但是 当我使用flask-restful后,路由分发用的 库里的Api
"""
from flask_restful import Api

api = Api(bp)


class ErrorApi(Resource):
    def get(self):
        return abort(404) # 注意此处的404
    
    
api.add_resource(ErrorApi, '/error')
当使用以上代码路由分发时,
访问   http://127.0.0.1:5000/error # 路由存在,自主abort(404)
反馈如下, 状态码 404
{
  "message": "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again."
}

访问   http://127.0.0.1:5000/error/s # 路由不存在,直接404
反馈如下, 状态码 404
{
  "msg": "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.",
  "error_code": 1001,
  "request": "GET /error/s"
}

后续我自主abort(405)
访问   http://127.0.0.1:5000/error # 路由存在,自主abort(405)
反馈如下, 状态码 405
{
  "message": "The method is not allowed for the requested URL."
}

解决思路

关于这部分我找了很久的资料,最后找到一个说法,如下图,具体的链接在底部
falsk-restful异常处理
原因找到了,要怎么解决呢?
之后由看到一边文章,【Flask-Restful在非调试模式下接管Flask的异常处理】
这里提出了重写API的error_router的思路
当然,我试过博主的方法,依旧没解决,但是这个想法让我看一部分Api的源码,然后找到了里面的handle_error这个函数,处理异常的函数。
我个人想到的思路就是重写该方法,让其不去处理异常,而是爆出异常,这样我们的全局异常捕获函数就能找到该异常

# base_api.py
rom flask_restful import Api as _Api
from werkzeug.exceptions import HTTPException


class Api(_Api):
    def handle_error(self, e):
        if isinstance(e, HTTPException):
            raise HTTPException()
        else:
            raise Exception()


api = Api()# 调用自定义的Api去路由分发
当使用以上代码路由分发时,
访问   http://127.0.0.1:5000/error # 路由存在,自主abort(404)
反馈如下, 状态码 404
{
  "msg": "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.",
  "error_code": 1001,
  "request": "GET /error"
}

访问   http://127.0.0.1:5000/error/s # 路由不存在,直接404
反馈如下, 状态码 404
{
  "msg": "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.",
  "error_code": 1001,
  "request": "GET /error/s"
}

后续我自主abort(405)
访问   http://127.0.0.1:5000/error # 路由存在,自主abort(405)
反馈如下, 状态码 405
{
  "msg": "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.",
  "error_code": 1001,
  "request": "GET /error/s"
}

至此,问题解决!
PS 重写的 Api 不确定会不会有其他问题,这个需要过多实践才行

相关资料

关于flask_restful的异常处理
Flask-Restful在非调试模式下接管Flask的异常处理


版权声明:本文为weixin_43868038原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_43868038/article/details/124727801