flask后端实践02-全局Response返回和异常处理

全局Response返回和异常处理

github

前言

主要谈在Python中,

  1. 如何进行统一Response处理。
  2. 如何进行全局异常处理。

定义全局Response

BizResponse

根据Flask所需参数,定义status,message,header

返回的header,我们很少关心

返回的status,按照业务返回即可。一般成功返回200。错误根据服务端错误和客户端错误自行确定,项目初期,可以区分下即可。

返回的message 即我们接口的返回体,一般返回Json类型格式

这里是我们重点关心的地方,要保证有统一的返回结构体。

代码详细请看

app/model/biz_response.py

思路

我们定义统一的biz_response来处理Flask的所有返回参数。

其中,对于参数message 要求必须实现dict_msg()这个函数

dict_msg()函数负责将出参映射成为希望看到的样子

定义装饰器

装饰器的感觉和java的注解类似,实现 dict_response

python 复制代码
def dict_response(cls):
    def dict_msg(cls):
        return {key: value for key, value in cls.__dict__.items()}

    cls.dict_msg = dict_msg
    return cls

@dataclass
@dict_response
class TestResponse:
    name: str
    age: int

通过装饰器dict_response, 为TestResponse增加一个dict_msg的方法。

上述的方法也可以手动实现

python 复制代码
class TestResponse:
    name: str
    age: int
    def dict_msg(cls):
      return {"name":cls.name, "age":cls.age}

额外学习:鸭子类型

python没有Java中的interface的概念。

python本身是支持鸭子类型的。和go中鸭子类型一样。所以不需要像java中定义interface。

python 复制代码
class Animal:
    def bark(cls):
        print("im a animal")

class Dog:
    def bark(cls):
        print("wang wang")

animal : Animal = Dog()
animal.bark() # wang wang
python3 复制代码
#biz_response.py
class BizResponse:
    def dict_msg(cls):
        return {
            "Response": cls.message.dict_msg()
        }

@dataclass
class TestResponse:
    id: str
    
    def dict_msg(cls):
        # 手动改为大写开头的格式
        return {
            "Id": cls.id,
        }

所以在BizResponse中,直接使用message的dict_msg()方法,不用关心具体的类型。

同时这也意味着我们所有的返回Response,都应该实现这个方法。
详细示例请看

到此为止,我们就能完全统一我们的返回结构体。

使用单元测试

使用unittest进行单元测试

https://docs.python.org/zh-cn/3/library/unittest.html

使用go test 的类似写法,使用xxx_test 进行命名。

定义业务异常

代码详细请查看 app/common/error.py

python 复制代码
#app/common/error.py
class ErrorCode(Enum):
    InternalError = "InternalError"
    InvalidParameter = "InvalidParameter"


class BizException(Exception):
    def __init__(cls, code: ErrorCode, message: str):
        cls.code = code
        cls.message = message


class Error:
    def __init__(cls, msg: str, code: str):
        cls.message = msg
        cls.code = code

    def dict_msg(cls):
        return {
            "Error": {
                "Message": cls.message,
                "Code": cls.code
            }
        }

定义业务异常的目的也是为了更好地通过错误代码错误,并判断错误原因。

个人倾向于使用string定义错误码。方便可读性。

定义全局异常处理

python 复制代码
@app.errorhandler(Exception)
def error_handler(e):
    """
    全局异常捕获
    """
    logger.error("error=%s", e)
    logger.error("traceback=%s", traceback.format_exc())
    if isinstance(e, BizException):
        message = e.message
        code = e.code.value
    else:
        message = f"error={e}"
        code = ErrorCode.InternalError.value
    response = BizResponse.fail(Error(message, code))
    return jsonify(response.dict_msg()), response.status, response.header
相关推荐
circuitsosk21 分钟前
从零搭建行业知识平台:向量库+图数据库+传统关系库的多模检索统一层设计
数据库·python·oracle·向量数据库·rag·多模检索
whcyhhh29 分钟前
头歌实践教学平台:大数据存储2023(十三3)
大数据·开发语言·python
AR-26710-38 分钟前
机器学习复习Day8——异常检测
人工智能·python·机器学习·scikit-learn
千里码aicood43 分钟前
Django 基于Django的电脑推荐与分析可视化系统设计与实现
python·django·电脑
Profile排查笔记43 分钟前
指纹浏览器手机版怎么选?从本地 App 到云端 Android 的实现方式解析
前端·人工智能·后端·自动化
jufeng13071 小时前
STM32F103 IAP 实战:串口 Bootloader 分区升级,掉电断电不白写
后端
未若君雅裁1 小时前
Agent 的结构化输出,ProviderStrategy、ToolStrategy 与错误重试
python·langchain
洛兮银儿1 小时前
pycharm选中同一个词的标记颜色的修改
ide·python·pycharm
Lost of 程序猿1 小时前
ASP.NET Core 多租户架构深度实战:一套系统,管理一支船队
后端·架构·asp.net
深念Y1 小时前
视频平台架构重构:从微服务到可插拔基础设施
后端·微服务·云原生·架构·rabbitmq·音视频·rocketmq