自定義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.pswp.cn/news/454034.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/454034.shtml
英文地址,請注明出處:http://en.pswp.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;選擇器…