在 python 開(kāi)發(fā)中,利用 flask 寫(xiě) restful api 函數(shù)的時(shí)候为迈,除了標(biāo)準(zhǔn)的400捌木、500等這些返回碼通過(guò) abort()
返回以外庸论,怎么另外返回自定義的錯(cuò)誤代碼和信息呢?
我們碰到的業(yè)務(wù)場(chǎng)景是對(duì)于api 輸入?yún)?shù)的各類(lèi)校驗(yàn)以及在業(yè)務(wù)邏輯執(zhí)行的時(shí)候厌均,都會(huì)返回統(tǒng)一的400代碼唬滑,同時(shí)也會(huì)返回我們約定的描述詳細(xì)錯(cuò)誤的代碼以及描述字符串,提供給調(diào)用方來(lái)處理,這樣可以讓其用戶體驗(yàn)做得更好间雀,同時(shí)詳細(xì)錯(cuò)誤代碼和描述字符串也會(huì)自動(dòng)打印在 log 日志中悔详。
flask 的官方文檔中告訴我們:
默認(rèn)情況下,錯(cuò)誤代碼會(huì)顯示一個(gè)黑白的錯(cuò)誤頁(yè)面惹挟。如果你要定制錯(cuò)誤頁(yè)面茄螃, 可以使用 errorhandler()
裝飾器
在寫(xiě) restful api 的時(shí)候,并沒(méi)有頁(yè)面可以返回连锯,我們可以在 flask 提供的代碼基礎(chǔ)上稍加改造如下归苍。
在你的初始化 flask app 的相關(guān)代碼中加入下面兩個(gè)函數(shù):
@app.errorhandler(CustomFlaskErr)
def handle_flask_error(error):
# response 的 json 內(nèi)容為自定義錯(cuò)誤代碼和錯(cuò)誤信息
response = jsonify(error.to_dict())
# response 返回 error 發(fā)生時(shí)定義的標(biāo)準(zhǔn)錯(cuò)誤代碼
response.status_code = error.status_code
return response
class CustomFlaskErr(Exception):
# 默認(rèn)的返回碼
status_code = 400
# 自己定義了一個(gè) return_code,作為更細(xì)顆粒度的錯(cuò)誤代碼
def __init__(self, return_code=None, status_code=None, payload=None):
Exception.__init__(self)
self.return_code = return_code
if status_code is not None:
self.status_code = status_code
self.payload = payload
# 構(gòu)造要返回的錯(cuò)誤代碼和錯(cuò)誤信息的 dict
def to_dict(self):
rv = dict(self.payload or ())
# 增加 dict key: return code
rv['return_code'] = self.return_code
# 增加 dict key: message, 具體內(nèi)容由常量定義文件中通過(guò) return_code 轉(zhuǎn)化而來(lái)
rv['message'] = J_MSG[self.return_code]
# 日志打印
logger.warning(J_MSG[self.return_code])
return rv
CustomFlaskErr
是我們自己寫(xiě)的處理錯(cuò)誤的類(lèi)运怖,然后通過(guò) @app.errorhandler(CustomFlaskErr)
這個(gè)裝飾器在 flask 中注冊(cè)拼弃。
具體功能在注釋里基本都寫(xiě)了,我們看一下怎么使用這個(gè)自定義錯(cuò)誤處理器摇展。
# 用戶名輸入為空
if user_name is None:
raise CustomFlaskErr(USER_NAME_ILLEGAL, status_code=400)
當(dāng)需要處理某個(gè)錯(cuò)誤的時(shí)候吻氧,rasie 剛才的 CustomFlaskErr,傳遞另外定義好的自己的錯(cuò)誤代碼咏连,以及標(biāo)準(zhǔn)的返回代碼盯孙;
上面說(shuō)的常量定義文件可以參考如下:
USER_ALREADY_EXISTS = 20001 # 用戶已經(jīng)存在
J_MSG = {USER_ALREADY_EXISTS: 'user already exists'}
通過(guò)這樣的機(jī)制,就做到了在具體 restful api 的業(yè)務(wù)邏輯代碼中簡(jiǎn)單的進(jìn)行各類(lèi)自定義錯(cuò)誤的處理祟滴,所有的錯(cuò)誤處理是集中的振惰,細(xì)顆粒度的錯(cuò)誤代碼和消息也是集中維護(hù),便于擴(kuò)展垄懂。
flask 官方文檔和一些網(wǎng)上的資料都說(shuō)比較簡(jiǎn)單骑晶,實(shí)踐中摸索了這樣的實(shí)現(xiàn)方式供參考。