flask異常處理


對於異常,通常可以分為兩類:一類是可以預知的異常,我們通常會用try...except....捕捉,第二類是未知的error,我們是無法預知的。

    try:

      code block

    except A:

      except A handle

    except:

      other except

    else:

      if no exception, excute here

    finally:

      code

    對於try....except捕捉異常,如果在try中發生了異常,會在except中捕捉到,並處理。如果沒有發生異常,會執行else語句

    但是不論異常是否發生,都會執行finally語句,所以我們一般會在finally語句中釋放資源。

但是,如果所有的代碼中我們都加上各種異常捕獲,會顯得代碼比較啰嗦,其實我們是可以將異常處理的邏輯提取出來,統一處理的。

1)下面我們先自定義已知異常處理,繼承自werkzeug.exceptions下面的HTTPException

  from flask import request, json

  from werkzeug.exceptions import HTTPException

  def APIException(HTTPException):

    code = 500

    msg = "sorry, we made a mistake"

    error_code = 500

    def __init__(msg=None, code=None, error_code=None):

      if code:

        self.code=code

      if msg:

        self.msg=msg

      if error_code:

        self.error_code = error_code

      super(APIException, self).__init__(self.msg, None)

    # 根據restful的特性,需要不論輸入還是輸出都需要是json格式,所以我們這里重寫get_body方法,將返回值定義為json格式

    def get_body(self, environ):

      resp = dict(

        msg = self.msg,

        error_code = self.error_code,

        request = request.method + " "+ self.get_url_without_param() # 告訴前端,是哪個接口除了問題

      )

      return json.dumps(resp)

    # 重寫get_header方法,告訴瀏覽器返回的是json格式,按照json格式解析

    def get_header():

      return [("content-type","application/json")]

    @staticmethod

    def get_url_without_param():

      full_url = str(request.full_path)

      main_url = full_url.split("?")

      return main_url[0]

 

  要使用我們的APIException也是很簡單的,如要處理參數異常,我們可以定義一個ParamError的類,繼承自APIException

    class ParamError(APIException):

      code =400

      msg = "invalid parameters"

      error_code = 1000 # 自定義

   然后在捕獲到參數異常的時候,直接拋出我們自定義的ParamError()即可

  如果是前端傳遞過來的參數驗證出異常的話,要使用我們的ParamException,需要手動的拋出異常,但是默認的wtforms會將錯誤信息放到errors中,而不會拋出異常,所以我們還需要重寫wtforms的驗證方法

    from wtforms import Form

    class BaseForm(Form):

      def __init__(self, data):

        # 調用父類的init方法

        super(BaseForm, self).__init__(data = data)

      def validate_for_api(self,):

        # 調用父類的驗證方法,如果驗證有問題,主動拋出ParamError異常 並將errors作為msg參數傳遞過去

        valid = super(BaseForm, self).validate()

        if not valid:

          # 這里的self 就是我們常規說的驗證的form

          raise ParamError(msg = self.errors)

        return self

  后面所有form直接繼承此BaseForm即可,然后在要驗證參數的地方調用重寫的validate_for_api即可。

2)我們定義個全局函數去統一處理所有的異常

  from werkzeug.exceptions import HTTPException

  # 使用裝飾器去捕捉異常 

  @app.errorhandler(Exception)

  def errorHandler(e):

    if isinstance(e, APIException):

      # 已知異常

      return e

    if isinstance(e, HTTPException):

      # HTTP異常

      code = e.code

      msg = e.description

      error_code = 1007 # 自定義

      return APIException(msg, code, error_code)

    else:

      # 其他未知異常,此處需要分是生產環境還是開發環境,如果是生產環境,返回json格式的異常,如果是開發環境,我們需要詳細的異常說明去分析異常原因

      if not app.config["DEBUG"]:

        return ServerError()  # 類似於上面定義的ParamError,自定義ServerError的code和msg

      else:

        raise e

 

這樣全局異常就處理完成,不論是發生何種異常,我們都能捕捉到並進行處理了。

      

    

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM