自定义python框架_Python web 框架Sanic 学习: 自定义 Exception

Sanic 是一个和类Flask 的基于Python3.5+的web框架,它使用了 Python3 异步特性,有远超 flask 的性能。

编写 RESTful API 的时候,我们会定义特定的异常错误类型,比如我定义的错误返回值格式为:

{

"error_code": 0,

"message": "string",

"text": "string"

}

不同的错误信息指定不同的 http 状态码。

sanic 提供了几种常用的 exception:

NotFound(404)

Forbidden(403)

ServerError(500)

InvalidUsage(400)

Unauthorized(401)

RequestTimeout(408)

PayloadTooLarge(413)

这些 exception 继承自 SanicException 类:

class SanicException(Exception):

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

super().__init__(message)

if status_code is not None:

self.status_code = status_code

从上述代码可以看出,这些异常只能指定 message 和 status_code 参数,那我们可不可以自定义 exception 然后在自定义的 exception 中增加参数呢?下面的代码是按照这个思路修改后的代码:

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

使用后我得到一个结果如下:

从结果可以发现,除了 http 状态码使我想要的其它全错,连 content-type 都是 text/plain; charset=utf-8,为什么会这样呢,我们定义的参数code 和 text 去了哪里?

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)

从源码可以看出,如果response 结果是 SanicException 类,response 处理方法会改用text,响应内容格式为 Error: status_code。

看来直接使用自定义异常类的方法不能满足我们上边定义的 json 格式(需要有 error_code、message 和 text)数据的要求。那我们能不能自定义 异常处理方法呢?答案当然是可以。

下面介绍两种自定义异常处理的方法:

使用 response.json

这种方法比较简单,既然 sanic 异常处理是把错误信息使用 response.text() 方法返回,那我们改成 response.json() 不就可以了么。sanic response 提供了 json 的响应对象。可以使用 response.json 定义一个错误处理方法:

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

return json(

{

'error_code': error_code,

'message': message,

'text': text

},

status=status_code)

这样我们只需要在需要抛出异常的地方 return json_error(code, msg, text, status_code)。

使用这种方法有一点需要注意:

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!')

这段代码中,如果我们没有找到用户信息,json_error 的返回结果会赋值给 account,并不会抛出异常,如果需要抛出异常,我们需要在 test 方法中检查 account 的结果,如果包含 account 是 response.json 对象, 直接 return, 更正后的代码如下:

@app.route("/")

async def test(request):

account = get_account()

if isinstance(account, response.json):

return account

return text('Hello world!')

这样虽然简单,但是会增加很多不必要的判断,那有没有方法可以直接抛出异常呢?这时就可以使用 sanic 提供的 @app.exception 装饰器了。

使用 Handling exceptions

sanic 提供了一个 @app.exception装饰器,使用它可以覆盖默认的异常处理方法。它的使用方法也很简单:

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))

这个装饰器允许我们传入一个需要捕获的异常的列表,然后,就可以在自定义方法中返回任意的响应数据了。

以下自定义的异常处理类:

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)

参考链接

最后,感谢女朋友支持。

欢迎关注(April_Louisa)

请我喝芬达

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/454034.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文字水印

using System.Threading.Tasks;using System.IO;using System.Drawing; public static int Shuy(string Sname,string fname) { try { Image image Image.FromFile(fname); Graphics gra Graphics.FromImage(image); String text Sname; Font font new Font("宋体&quo…

读书笔记2013第3本:《无价》

《无价》这本书是过年前买的,网络书店上写着“老罗推荐”,想着好像是在老罗哪一年的演讲里听过这本书,在豆瓣上评分7.9。读书是为了产生行动,读书时要提的4个问题,1)这本书主要在谈些什么?2&…

Linux下的程序调试——GDB

无论是多么优秀的程序员,都难以保证自己在编写代码时不会出现任何错误,因此调试是软件开发过程中的一个必不可少的 组成部分。当程序完成编译之后,它很可能无法正常运行,或者会彻底崩溃,或者不能实现预期的功能。此时如…

圆锥曲线万能弦长公式_2020高考数学50条秒杀型公式与方法

考试马上就要到了,学姐整理了高考数学50条秒杀型公式和方法,希望能帮助考生们更好地攻克数学难关!高考数学秒杀公式与方法一1,适用条件:[直线过焦点],必有ecosA(x-1)/(x1),其中A为直线与焦点所在…

Python 内置模块之 logging

日志的级别和适用情况 级别适用情况DEBUG详细信息,通常只在诊断问题时对其感兴趣INFO确认工作正常WARNING表示发生了意料之外的事或者在不远的将来会有问题(比如磁盘空间低)。软件依然正常工作ERROR由于一个更加严重的问题,软件不…

Memory barrier

待续 Memory barrier,是一种屏障和一类指令,在执行这个屏障指令前后,CPU或者编译器在内存操作上强制一个约束序列。CPU使用性能优化器可以导致执行代码的无序。在单一线程执行中,重排序内存操作通常不会被注意。但是在并行编程或者设备驱动中…

数据结构与算法 Python语言描述 笔记

数据结构 线性表包括顺序表和链表,python的list是顺序表,链表一般在动态语言中不会使用。不过链表还是会出现在各种算法题中。 链表 link list 单链表 逆转链表: leetcode 206双链表循环单链表字符串 string 有一个重要的点就是字符串的匹配问…

Flask 跨域问题

一、什么是跨域 跨域是指:浏览器A从服务器B获取的静态资源,包括Html、Css、Js,然后在Js中通过Ajax访问C服务器的静态资源或请求。即:浏览器A从B服务器拿的资源,资源中想访问服务器C的资源。 同源策略是指:…

Hibernate 中配置属性详解(hibernate.properties)

转自:https://blog.csdn.net/shudaqi2010/article/details/70324843 Hibernate能在各种不同环境下工作而设计的, 因此存在着大量的配置参数。多数配置参数都 有比较直观的默认值, 并有随 Hibernate一同分发的配置样例hibernate.properties 来展示各种配置选项。 所需…

1.3 使用电脑测试MC20的电话语音功能

需要准备的硬件 MC20开发板 1个https://item.taobao.com/item.htm?id562661881042GSM/GPRS天线 1根https://item.taobao.com/item.htm?id531979567261IPEX接口转SMA接口转接线 1根https://item.taobao.com/item.htm?id531979903836GPS有源天线 1根https://item.taobao.com/i…

前端之 AJAX

AJAX参数详细列表 参数名类型描述urlString(默认: 当前页地址) 发送请求的地址。typeString(默认: "GET") 请求方式 ("POST" 、 "GET")。注意:其它 HTTP 请求方法,如 PUT 和 DELETE ,但仅部分浏览器支持。tim…

buffer 和cache的区别

Cache:高速缓存,是位于CPU与主内存间的一种容量较小但速度很高的存储器。 由于CPU的速度远高于主内存,CPU直接从内存中存取数据要等待一定时间周期,Cache中保存着CPU刚用过或循环使用的一部分数据,当CPU再次使用该部分…

html5--1.18 div元素与布局

1.18 div元素与布局 1.元素的分类2.div元素与布局 1、元素的分类 块元素:主要特征是会产生换行效果,自动与其他元素分离成两行;通常可以作为容器在内部添加其他元素。已经学过的块元素有: h1~h6;hr;ul;ol;p;table......... 内联元素:不会产生…

python读取excel表格太大怎么办_Python:使用Openpyxl读取大型Excel工作表

尝试对load_workbook()类使用read_only True属性,这会导致您获得的工作表为IterableWroksheet,这意味着您只能迭代它们,您不能直接使用列/行号来访问其中的单元格值.根据documentation,这将提供接近恒定的存储器消耗.此外,您不需要关闭文件,语句将为您处理.示例 –import open…

五个优秀的视频格式转换工具

电脑、手机、DVD播放机、PSP……这么多的东西都可以播放视频,但是视频格式又千差万别的,我们该怎么办?这里,我们介绍五个功能强大且易于使用的媒体转换器,用于转换不同类型的视频文件。 一、Super (Windows) Super是一…

前端之 HTML

HTML Web服务本质 import socketsk socket.socket() sk.bind(("127.0.0.1", 8080)) sk.listen(5)while True:conn, addr sk.accept()data conn.recv(8096)conn.send(b"HTTP/1.1 200 OK\r\n\r\n")conn.send(b"<h1>Hello world!</h1>&…

接入指南

接入概述 接入微信公众平台开发&#xff0c;开发者需要按照如下步骤完成&#xff1a; 1、填写服务器配置 2、验证服务器地址的有效性 3、依据接口文档实现业务逻辑 下面详细介绍这3个步骤。 第一步&#xff1a;填写服务器配置 登录微信公众平台官网后&#xff0c;在公众平台官网…

艾宾浩斯记忆表格excel_Excel全年学习复习计划表(艾宾浩斯遗忘曲线)

最近准备考在职博士&#xff0c;刷刷学历&#xff0c;不得不又拿起必考的英语来&#xff0c;发现由于这几年敲代码&#xff0c;日常生活词汇忘了很多&#xff0c;只好买本考博词汇背诵&#xff0c;不过三十而立的人背起来确实费劲了&#xff0c;所以开始寻找好的背诵方法。又想…

七个帮助你处理Web页面层布局的jQuery插件

1.UI.Layout jQuery UI布局插件官方网站&#xff1a;http://layout.jquery-dev.com/index.cfm使用大小可折叠的嵌套面板和大量选项创建高级UI布局。布局可以创建任何你想要的UI外观; 从简单的标题或侧边栏到具有工具栏&#xff0c;菜单&#xff0c;帮助面板&#xff0c;状态栏…

前端之 CSS

CSS介绍 CSS&#xff08;Cascading Style Sheet&#xff0c;层叠样式表)定义如何显示HTML元素。 当浏览器读到一个样式表&#xff0c;它就会按照这个样式表来对文档进行格式化&#xff08;渲染&#xff09;。 CSS语法 CSS实例 每个CSS样式由两个组成部分&#xff1a;选择器…