python

监测异常

try:
	<语句>        #运行别的代码
except <名字><语句>         #如果在try部份引发了'name'异常
except <名字><数据>:
	<语句>         #如果引发了'name'异常,获得附加的数据
else:
	<语句>         #如果没有异常发生
finaly:
	<语句>         #总会执行

try的工作原理是,当开始一个try语句后,python就在当前程序的上下文中作标记,这样当异常出现时就可以回到这里,try子句先执行,接下来会发生什么依赖于执行时是否出现异常。

  • 如果当try后的语句执行时发生异常,python就跳回到try并执行第一个匹配该异常的except子句,异常处理完毕,控制流就通过整个try语句(除非在处理异常时又引发新的异常)。
  • 如果在try后的语句里发生了异常,却没有匹配的except子句,异常将被递交到上层的try,或者到程序的最上层(这样将结束程序,并打印默认的出错信息)。
  • 如果在try子句执行时没有发生异常,python将执行else语句后的语句(如果有else的话),然后控制流通过整个try语句。

触发异常

raise Exception()

golang

监测异常

if err != nil {
	
}

flask

@app.errorhandler(Exception)
def handler_api_exception(exception):
    return my_func(exception)

django

viewset(raise)

class UsersGenericMixinAPIView(ListModelMixin,
                                  CreateModelMixin,
                                  RetrieveModelMixin,
                                  UpdateModelMixin,
                                  DestroyModelMixin,
                                  GenericViewSet):
    queryset = Work.objects.all()
    serializer_class = 
    filter_class =
    filter_backends = (DjangoFilterBackend, OrderingFilter)
    ordering = ("name",)
    pagination_class = None
 
    def create(self, request, *args, **kwargs):
      try:
        ...
      except Exception as e:
        loging.errinfo(str(e))
        from rest_framework.exceptions import APIException
        raise APIException("info")
      return Response()

 # setting 中drf自定义配置,如分页器,鉴权器,异常处理函数等
 REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'utils.custom_exceptions.custom_exception_handler'
}
 
 # 拦截器中使用了rest_frameworkz中的e exception_handler处理exception,同时可以做一些定义处理
from rest_framework.views import exception_handler
def custom_exception_handler(exc, context):
    response = exception_handler(exc, context)
    if response is not None:
        response.data['code'] = response.data.get('code') or response.status_code
        if response.data.get('msg'):
            response.data['msg'] = response.data.get('msg')
        elif response.data.get('id'):
            response.data['msg'] = response.data.get('id')[0]
        elif response.data.get('detail'):
            response.data['msg'] = response.data.get('detail')
        else:
            response.data['msg'] = '参数有误!!'
    return response

APIView(not raise)

class UserView(APIView): 
	def get(req):
		try:
			...
		except:
			return Response()
		return Response()

gin

panic

使用pannic,然后用一个recover的中间件将程序恢复回来

e.Use(RecoveryMiddleware(DefaultStopExecHandler))

func RecoveryMiddleware(f func(c *gin.Context, err error)) gin.HandlerFunc {
	return func(c *gin.Context) {
		defer func() {
			if err := recover(); err != nil {
				f(c, err.(error))
			}
		}()

		c.Next()
	}
}

func StopExec(err error) {
	if err == nil {
		return
	}
	panic(err)
}

// 提供一个默认的 recoveryhandler
func DefaultStopExecHandler(c *gin.Context, err error) {
	returnfun.ReturnJson(c, 400, 400, err.Error(), "")
}

return

顶层处理错误,直接返回错误对应的状态码

func handleError(c *gin.Context, code int, err error) {
	response := map[string]string{}
	response["message"] = err.Error()
	c.JSON(code, response)
}

疑问

在程序的异常处理中到底是应该使用顶层处理err返回结果,还是应该pannic,raise???

  • 如果顶层处理err,结果可控,可以返回用户定义的错误,但是如果涉及多层调用的时候err要逐层传递到可以处理的位置

  • 如果raise or pannic 对于程序来说是不友好,返回结果不可控,但是可以错误在哪里就直接处理

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐