Dowemo

Sanic is a python3 -based -based web framework with a class. Which uses asynchronous features, with, properties.

When writing a submenu api, we define a specific exception type, such as the error return format that I define:


{


"error_code": 0,


"message":"string",


"text":"string"


}


Different error messages specify different http status codes.

Sanic provides several common exceptions:

  • ( 404 )

  • Forbidden ( 403 )

  • ServerError ( 500 )

  • Invalidusage ( 400 )

  • Unauthorized ( 401 )

  • RequestTimeout ( 408 )

  • Payloadtoolarge ( 413 )

These exceptions inherit from the sanicexception class:


class SanicException(Exception):



 def __init__(self, message, status_code=None):


 super().__init__(message)



 if status_code is not None:


 self.status_code = status_code


As you can see from the above code, these exceptions can only specify the message and status_code parameters, so we can customize the exception and then add the The following code is modified according to this idea:


class ApiException(SanicException):



 def __init__(self, code, message=None, text=None, status_code=None):


 super().__init__(message)


 self.error_code = code


 self.message = message


 self.text = text



 if status_code is not None:


 self.status_code = status_code


After use I get a result as follows:

From the results you can find that other than the http state, the other I want, even content-type is text/plain; charset=utf-8, why would we've defined the parameter code and the

Open the code for sanic https://github.com/channelcat/sanic/blob/master/sanic/handlers.py, and I found the answer:


def default(self, request, exception):


 self.log(format_exc())


 if issubclass(type(exception), SanicException):


 # 如果是 SanicException 类,返回格式是定义好的,


 # response 处理方法用的是 text


 return text(


 'Error: {}'.format(exception),


 status=getattr(exception, 'status_code', 500),


 headers=getattr(exception, 'headers', dict())


 )


 elif self.debug:


 html_output = self._render_traceback_html(exception, request)



 response_message = (


 'Exception occurred while handling uri:"{}"n{}'.format(


 request.url, format_exc()))


 log.error(response_message)


 return html(html_output, status=500)


 else:


 return html(INTERNAL_SERVER_ERROR_HTML, status=500)


As you can see from the source code, if the response is a sanicexception class, the response processing method uses text instead of Error: status_code.

It appears that methods that use custom exception classes directly cannot satisfy the json format defined above ( requiring error_code, message, and text ) data. Can we customize the exception handling method. .

The following two methods for custom exception handling are described:

Using response. Json.

This method is simple, since the sanic exception handling is to use the response, text ( ) method back to the response. The sanic response provides the respo & e object for the json. You can define a error handling method by using response.json:


def json_error(error_code, message, text, status_code):


 return json(


 {


 'error_code': error_code,


 'message': message,


 'text': text


 },


 status=status_code)


So we just need to throw an exception where we need to throw an exception. return json_error(code, msg, text, status_code) .

There's a point in using this method:





def get_account():


. . .


 if account:


 return account


 else:


 # 如果用户没找到 返回错误信息


 return json_error(code, msg, text, status_code)



@app.route("/")


async def test(request):


 account = get_account()


 return text('Hello world!')


In this code, if we don't find the user information, the return result of the json_error is assigned to account, and no exception is thrown. If an exception is thrown, the.


@app.route("/")


async def test(request):


 account = get_account()


 if isinstance(account, response.json):


 return account


 return text('Hello world!')


This is simple, but will add a lot of unnecessary judgment, and there's no way to throw an exception directly. You can then use the @app.exception adorner provided by sanic.

Use handling width

Sanic provides a @app.exception adorner that can override the default exception handling method. It's also simple to use:


from sanic.response import text


from sanic.exceptions import NotFound



@app.exception(NotFound)


def ignore_404s(request, exception):


 return text("Yep, I totally found the page: {}".format(request.url))


This adorner allows us to pass in a list of exceptions that need to be captured, and then we can return to any response data in the custom method.

The following custom exception handling classes:


error_codes = {


 'invalid_token': ('Invalid token', '无效的token'),


}



def add_status_code(code):


"""


 Decorator used for adding exceptions to _sanic_exceptions.


"""


 def class_decorator(cls):


 cls.status_code = code


 return cls


 return class_decorator



class MetisException(SanicException):



 def __init__(self, code, message=None, text=None, status_code=None):


 super().__init__(message)


 self.error_code = code


 _message, _text = error_codes.get(code, (None, None))


 self.message = message or _message


 self.text = text or _text



 if status_code is not None:


 self.status_code = status_code



@add_status_code(404)


class NotFound(MetisException):


 pass



@add_status_code(400)


class BadRequest(MetisException):


 pass



# 使用 app.exception 捕获异常,返回自定义响应数据


@app.exception(Unauthorized, NotFound, BadRequest)


def json_error(request, exception):


 return json(


 {


 'error_code': exception.error_code,


 'message': exception.message,


 'text': exception.text


 },


 status=exception.status_code)


Reference link

Finally, thank you for your.

Welcome to focus ( april_louisa ), please.



Copyright © 2011 Dowemo All rights reserved.    Creative Commons   AboutUs