Python项目之异常处理

异常处理

在项目中,难免会有bug。 我们需要把这些可能出现的异常捕获到然后做处理,既不影响项目的运行又可以看到错误的输出, 下面以我经常用到的技术栈flask+mongoengine举个例子?‍♂️

一. 全局异常捕获,封装装饰器

    大家都知道,使用try: except可以捕获错误类型及输出, 如果不确定可能出现的错误类型,则可以用Exception捕获

try:
    print(a)
except Exception:
    pass

    那么我们可以将接口中运行的代码段放到try中,在此基础上封装个装饰器,可以通过简单的调用装饰器函数使每个需要捕获错误的代码段都能正常运行

封装

# app/utils/common.py

# 状态异常
def abnormal_return(msg):
    return {
        "code": 10000,
        "data": "",
        "msg": msg
    }

# 错误判断
def catch_exception(origin_func):
    def wrapper(self, *args, **kwargs):
        from flask import current_app
        try:
            u = origin_func(self, *args, **kwargs)
            return u
        except Exception as e:
            result = repr(e)
            return abnormal_return(result)
    return wrapper

调用

from utils.common import catch_exception
from flask_restful import Resource

# 函数
@catch_exception
def add(a, b):
    return a+b

# 类
class GetInfoAPI(Resource)
	@catch_exception
	def post(self):
        data = request.json
        ...
        return data

二. 自定义错误码

    全局错误处理完,就要对用户的操作出现的不同情况进行反馈,让前端能根据不同的错误码来返回用户能看懂的错误信息,比如无权访问用户名/密码错误验证码错误等等

    最经典的就是浏览器与服务器交互返回的状态码200\404\500等等,一看就知道问题在哪

    来看看常见第三方API的错误码定义

    钉钉

    微信

    可以看到是各不相同,错误码是在项目开发前根据项目的具体业务场景定义的

    所以我要说的是封装错误请求的返回,而不是如何定义错误码

    像这样在一个常量文件中去定义错误码与msg

# apps/utils/common.py
from ... import ERROR_CODE_DEFINE

# 自定义错误码
def error_return(code, data):
    return {
        "code": code,
        "data": data,
        "msg": ERROR_CODE_DEFINE[code]
    }

# 调用
def demmo(a,b):
    if not a:
        return error_return(40001, "这只是个测试")

三. model异常捕获

ORM语法为了避免do not exist错误,大家基本告别了get,都使用filter,判断存在后取first

Emmm 其实有个get_or_404,用起来感觉比较鸡肋,因为404还是报错

其实我们是希望它 有则返回queryset object,无则返回None,不报错就行

我想的一个最笨的方法就是写成model的一个函数,然后调用, 像这样

# apps/users/models.py

class Staff(db.Document):
    name = db.StringField()
    ...
    
    @staticmethod
    def get_or_none(**kwargs):
        obj = Staff.objects(**kwargs)
        result = None
        if obj:
            result = obj[0]
        return result

麻烦的就是每个model都得封装一次,不过想想如果不用每次都封装,就得写个自定义objects来代替原本的querySet manager,然后每个model里都要加一句 objects=MyManager(),好像差不多。就暂时先这样

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页