flask異常處理:abort、errorhandler、app_errorhandler,封裝全局異常處理

[toc]html

1. abort()

abort()函數也叫視圖終止函數,用於提早退出一個請求,並用指定的錯誤碼返回。既然是視圖終止函數,就是說abort()函數是寫在視圖中的。那麼這個函數就不能處理因爲url不合法引發的異常,由於一旦url不合法,是沒法進入到視圖函數中的。前端

flask-restful中的 abort() 的代碼是封裝的 flask 的 abort() 代碼。python

flask abort() 源碼:json

def abort(status, *args, **kwargs):
    return _aborter(status, *args, **kwargs)

flask-restful 的 abort() 源碼:flask

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狀態碼。restful

直接返回給前端頁面一個對應錯誤碼的錯誤信息。app

查看錯誤碼:函數

from werkzeug.exceptions import default_exceptions
import pprint

pprint.pprint(default_exceptions)

結果:ui

若是是如下列表以外的,會報服務器內部錯誤:{"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 封裝成全局異常捕獲處理:

  1. 自定義異常類(有須要的話)
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
  1. 捕獲異常並處理:
# 制定一個響應
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狀態,也會被捕捉,進行處理

參考文章:

  1. http://www.javashuo.com/article/p-urtewknv-nm.html
  2. https://www.cnblogs.com/fiona-zhong/p/10218338.html
相關文章
相關標籤/搜索