1. abort()
abort()函數也叫視圖終止函數,用於提前退出一個請求,並用指定的錯誤碼返回。既然是視圖終止函數,就是說abort()函數是寫在視圖中的。那么這個函數就不能處理由於url不合法引起的異常,因為一旦url不合法,是無法進入到視圖函數中的。
flask-restful中的 abort() 的代碼是封裝的 flask 的 abort() 代碼。
flask abort() 源碼:
def abort(status, *args, **kwargs):
return _aborter(status, *args, **kwargs)
flask-restful 的 abort() 源碼:
def abort(http_status_code, **kwargs):
try:
original_flask_abort(http_status_code)
except HTTPException as e:
if len(kwargs):
e.data = kwargs
raise
這里的 original_flask_abort() 即 flask 的 abort()。其實我們也可以自己來封裝abort()這個函數,來實現我們需要的功能。
1.1 使用方式一:傳遞一個錯誤碼
from flask import abort
@app.route("/")
def index():
# abort函數可以提前終止視圖函數
abort(404)
# 下面這條消息無法打印出來,因為上面abort函數已經終止了這個視圖函數的運行。
print("我還在運行ing")
return "Index Page"
參數http_status_code:傳遞狀態碼(錯誤碼),必須是標准的http狀態碼。
直接返回給前端頁面一個對應錯誤碼的錯誤信息。
查看錯誤碼:
from werkzeug.exceptions import default_exceptions
import pprint
pprint.pprint(default_exceptions)
結果:
如果是以下列表之外的,會報服務器內部錯誤:{"message": "Internal Server Error"}
可以看到2xx與3xx並不在此之列。
{400: <class 'werkzeug.exceptions.BadRequest'>,
401: <class 'werkzeug.exceptions.Unauthorized'>,
403: <class 'werkzeug.exceptions.Forbidden'>,
404: <class 'werkzeug.exceptions.NotFound'>,
405: <class 'werkzeug.exceptions.MethodNotAllowed'>,
406: <class 'werkzeug.exceptions.NotAcceptable'>,
408: <class 'werkzeug.exceptions.RequestTimeout'>,
409: <class 'werkzeug.exceptions.Conflict'>,
410: <class 'werkzeug.exceptions.Gone'>,
411: <class 'werkzeug.exceptions.LengthRequired'>,
412: <class 'werkzeug.exceptions.PreconditionFailed'>,
413: <class 'werkzeug.exceptions.RequestEntityTooLarge'>,
414: <class 'werkzeug.exceptions.RequestURITooLarge'>,
415: <class 'werkzeug.exceptions.UnsupportedMediaType'>,
416: <class 'werkzeug.exceptions.RequestedRangeNotSatisfiable'>,
417: <class 'werkzeug.exceptions.ExpectationFailed'>,
418: <class 'werkzeug.exceptions.ImATeapot'>,
422: <class 'werkzeug.exceptions.UnprocessableEntity'>,
423: <class 'werkzeug.exceptions.Locked'>,
428: <class 'werkzeug.exceptions.PreconditionRequired'>,
429: <class 'werkzeug.exceptions.TooManyRequests'>,
431: <class 'werkzeug.exceptions.RequestHeaderFieldsTooLarge'>,
451: <class 'werkzeug.exceptions.UnavailableForLegalReasons'>,
500: <class 'werkzeug.exceptions.InternalServerError'>,
501: <class 'werkzeug.exceptions.NotImplemented'>,
502: <class 'werkzeug.exceptions.BadGateway'>,
503: <class 'werkzeug.exceptions.ServiceUnavailable'>,
504: <class 'werkzeug.exceptions.GatewayTimeout'>,
505: <class 'werkzeug.exceptions.HTTPVersionNotSupported'>}
1.2 使用方式二:傳遞一個json格式字符串
from flask import abort, jsonify
@app.route("/")
def index():
code = 50000
data = [{"data1": "lalallala", {"data2": "lolololo"}]
json_data = jsonify({"code": code, "data": data})
abort(json_data)
# 下面這條消息無法打印出來,因為上面abort函數已經終止了這個視圖函數的運行。
print("我還在運行ing")
return "Index Page"
這種方法相當於 return ,直接把傳入abort中的數據返回到前端。
1.3 使用方式三:傳遞一個響應體
from flask import abort, Response
@app.route("/")
def index():
res = Response("Not Found", 404, {"name": "ttytty"}) # Response也可以返回響應體信息
abort(res)
# 下面這條消息無法打印出來,因為上面abort函數已經終止了這個視圖函數的運行。
print("我還在運行ing")
return "Index Page"
直接返回給前端這個響應體。方式二和方式三很相似。
2. errorhandler
捕捉當前app或藍圖的狀態碼,然后可以進行自定義處理。
2.1 簡單使用:
from flask import jsonify
from . import admin
@admin.errorhandler(404)
def error_404(error):
"""這個handler可以catch住所有abort(404)以及找不到對應router的處理請求"""
response = dict(status=0, message="404 Not Found")
return jsonify(response), 404
@admin.errorhandler(Exception)
def error_500(error):
"""這個handler可以catch住所有的abort(500)和raise exeception."""
response = dict(status=0, message="500 Error")
return jsonify(response), 400
class MyError(Exception):
"""自定義錯誤類"""
pass
@admin.errorhandler(MyError)
def MyErrorHandle(error):
response = dict(status=0, message="400 Error")
return jsonify(response), 400
2.2 封裝成全局異常捕獲處理:
- 自定義異常類(有需要的話)
from werkzeug.exceptions import HTTPException
class EigenException(HTTPException):
code = 500
eigen_code = 4000
description = 'Inner Server Error'
class RequestError(EigenException):
code = 400
class DataNotFound(RequestError):
code = 404
eigen_code = 4004
description = 'Data Not Found'
def __init__(self, message):
self.description = '%s Not Found' % message
class InvalidRequest(RequestError):
eigen_code = 4005
description = 'Invalid Request URL'
class MissingKey(RequestError):
eigen_code = 4006
description = 'Missing Key'
def __init__(self, key):
self.description = 'Missing Key `%s`' % key
- 捕獲異常並處理:
# 制定一個響應
def json_response(code, error, status_code):
response = make_response(json.dumps(dict(code=code, error=error)), status_code)
response.headers['Content-Type'] = 'application/json; charset=utf-8'
return response
# 異常捕獲處理
@app.errorhandler(Exception)
def handler_exception(e):
if isinstance(e, 其他異常):
code, status_code, error = 4000, 400, e.description
elif isinstance(e, EigenException):
code, status_code, error = e.eigen_code, e.code, e.description
elif isinstance(e, HTTPException):
code, status_code, error = e.code, e.code, e.description
else:
code, status_code, error = 5000, 500, '%s(%s)' % (e.__class__.__name__, str(e))
return json_response(code, error, status_code)
3. app_errorhandler
捕捉全局狀態碼,並進行自定制異常處理
在藍本中編寫錯誤處理程序有點不同,如果使用errorhandler修飾器,那么只有藍本中的錯誤才會觸發。如果想注冊全局的錯誤處理程序,要用app_errorhandler。
例如:
from bookapp import bokkapp
@bookapp.app_errorhandler(Exception)
def handler_exception(e):
if isinstance(e, 其他異常):
code, status_code, error = 4000, 400, e.description
elif isinstance(e, EigenException):
code, status_code, error = e.eigen_code, e.code, e.description
elif isinstance(e, HTTPException):
code, status_code, error = e.code, e.code, e.description
else:
code, status_code, error = 5000, 500, '%s(%s)' % (e.__class__.__name__, str(e))
response = dict(code=code, status=status_code, msg=error)
return jsonify(response)
**注意: **當我們不是使用的工廠模式創建app時,app.errorhandler(401),即可捕捉全局401狀態;若使用了create_app方式創建app,則無法進行捕捉,若想捕捉,可以在藍圖中寫,如admin.errorhandler(401),即捕捉admin藍圖下所有401狀態碼,admin.app_errorhandler(401),則是捕捉的全局的401狀態碼,即其他藍圖中的401狀態,也會被捕捉,進行處理
參考文章: