人妖在线一区,国产日韩欧美一区二区综合在线,国产啪精品视频网站免费,欧美内射深插日本少妇

新聞動態(tài)

詳解Flask開發(fā)技巧之異常處理

發(fā)布日期:2022-03-10 15:12 | 文章來源:腳本之家

一、Flask內(nèi)置異常處理

要想在Flask中處理好異常,有一套自己的異常處理機制,首先,我們必須先知道Flask自己是如何處理異常的。去flask的源碼里找一找會發(fā)現(xiàn),在flask源碼的app.py文件下,有很多會拋出異常的方法,其中拿一個舉例:

def handle_exception(self, e):
"""Default exception handling that kicks in when an exception
occurs that is not caught.  In debug mode the exception will
be re-raised immediately, otherwise it is logged and the handler
for a 500 internal server error is used.  If no such handler
exists, a default 500 internal server error message is displayed.
.. versionadded:: 0.3
"""
exc_type, exc_value, tb = sys.exc_info()
got_request_exception.send(self, exception=e)
handler = self._find_error_handler(InternalServerError())
if self.propagate_exceptions:
 # if we want to repropagate the exception, we can attempt to
 # raise it with the whole traceback in case we can do that
 # (the function was actually called from the except part)
 # otherwise, we just raise the error again
 if exc_value is e:
  reraise(exc_type, exc_value, tb)
 else:
  raise e
self.log_exception((exc_type, exc_value, tb))
if handler is None:
 return InternalServerError()
return self.finalize_request(handler(e), from_error_handler=True)

我們發(fā)現(xiàn)在flask內(nèi)部對于500異常,會拋出這樣一個錯誤類InternalServerError()

class InternalServerError(HTTPException):

......

至此我們發(fā)現(xiàn)flask內(nèi)部異常通過繼承這個HTTPException類來處理,那么這個HTTPException類就是我們研究的重點。

二、HTTPException類分析

@implements_to_string
class HTTPException(Exception):
 """Baseclass for all HTTP exceptions.  This exception can be called as WSGI
 application to render a default error page or you can catch the subclasses
 of it independently and render nicer error messages.
 """
 code = None
 description = None
 def __init__(self, description=None, response=None):
  super(HTTPException, self).__init__()
  if description is not None:
self.description = description
  self.response = response
 @classmethod
 def wrap(cls, exception, name=None):
  """Create an exception that is a subclass of the calling HTTP
  exception and the ``exception`` argument.
  The first argument to the class will be passed to the
  wrapped ``exception``, the rest to the HTTP exception. If
  ``e.args`` is not empty and ``e.show_exception`` is ``True``,
  the wrapped exception message is added to the HTTP error
  description.
  .. versionchanged:: 0.15.5
The ``show_exception`` attribute controls whether the
description includes the wrapped exception message.
  .. versionchanged:: 0.15.0
The description includes the wrapped exception message.
  """
  class newcls(cls, exception):
_description = cls.description
show_exception = False
def __init__(self, arg=None, *args, **kwargs):
 super(cls, self).__init__(*args, **kwargs)
 if arg is None:
  exception.__init__(self)
 else:
  exception.__init__(self, arg)
@property
def description(self):
 if self.show_exception:
  return "{}\n{}: {}".format(self._description, exception.__name__, exception.__str__(self)
  )
 return self._description
@description.setter
def description(self, value):
 self._description = value
  newcls.__module__ = sys._getframe(1).f_globals.get("__name__")
  name = name or cls.__name__ + exception.__name__
  newcls.__name__ = newcls.__qualname__ = name
  return newcls
 @property
 def name(self):
  """The status name."""
  from .http import HTTP_STATUS_CODES
  return HTTP_STATUS_CODES.get(self.code, "Unknown Error")
 def get_description(self, environ=None):
  """Get the description."""
  return u"<p>%s</p>" % escape(self.description).replace("\n", "<br>")
 def get_body(self, environ=None):
  """Get the HTML body."""
  return text_type(
(
 u'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n'
 u"<title>%(code)s %(name)s</title>\n"
 u"<h1>%(name)s</h1>\n"
 u"%(description)s\n"
)
% {
 "code": self.code,
 "name": escape(self.name),
 "description": self.get_description(environ),
}
  )
 def get_headers(self, environ=None):
  """Get a list of headers."""
  return [("Content-Type", "text/html; charset=utf-8")]
 def get_response(self, environ=None):
  """Get a response object.  If one was passed to the exception
  it's returned directly.
  :param environ: the optional environ for the request.  Thiscan be used to modify the response dependingon how the request looked like.
  :return: a :class:`Response` object or a subclass thereof.
  """
  from .wrappers.response import Response
  if self.response is not None:
return self.response
  if environ is not None:
environ = _get_environ(environ)
  headers = self.get_headers(environ)
  return Response(self.get_body(environ), self.code, headers)
  • 截取這個類比較重要的幾個方法分析,get_headers方法定義了這個返回的響應(yīng)頭,返回的是html文檔。
  • get_body方法定義了返回的響應(yīng)體,對應(yīng)也是一段html的內(nèi)容。
  • 最后在Response中將響應(yīng)體,狀態(tài)碼,響應(yīng)頭定義好返回。

分析至此,其實這個HTTPException中做的事也不難理解,就是定義好響應(yīng)體,狀態(tài)碼,還有響應(yīng)頭,做了一個返回。當(dāng)然這個類返回是html類型的,現(xiàn)在前后端分離交互都是json形式的返回,所以我們可以繼承自這個類,定義我們自己的異常處理類。

三、自定義異常處理類

首先我們理解我們自己的這個異常處理類,應(yīng)該繼承自HTTPException來改寫。而我們自定義的內(nèi)容應(yīng)該包含以下幾點:

  • 需要定義我們自己想要返回的錯誤信息的json格式,比如內(nèi)部錯誤碼、錯誤信息等我們想記錄的信息。
  • 需要更改返回的響應(yīng)頭,返回json格式的信息響應(yīng)頭就應(yīng)該設(shè)為'Content-Type': 'application/json'
  • 同樣需要和HTTPException一樣定義好狀態(tài)碼

如下定義我們自己的異常類APIException,返回的信息包括內(nèi)部錯誤碼,錯誤信息,請求的url

class APIException(HTTPException):
 code = 500
 msg = 'sorry, we made a mistake!'
 error_code = 999
 def __init__(self, msg=None, code=None, error_code=None, headers=None):
  if code:
self.code = code
  if error_code:
self.error_code = error_code
  if msg:
self.msg = msg
  super(APIException, self).__init__(msg, None)
 def get_body(self, environ=None):
  body = dict(
msg=self.msg,
error_code=self.error_code,
request=request.method + ' ' + self.get_url_no_param()
  )
  text = json.dumps(body)
  return text
 def get_headers(self, environ=None):
  """Get a list of headers."""
  return [('Content-Type', 'application/json')]
 @staticmethod
 def get_url_no_param():
  full_path = str(request.full_path)
  main_path = full_path.split('?')
  return main_path[0]

四、方便的定義自己的錯誤類

有了上面我們改寫好的APIException類,我們就可以自由的定義各種狀態(tài)碼的錯誤以及對應(yīng)的錯誤信息,然后在合適的位置拋出。比如:

class Success(APIException):
 code = 201
 msg = 'ok'
 error_code = 0

class DeleteSuccess(APIException):
 code = 202
 msg = 'delete ok'
 error_code = 1

class UpdateSuccess(APIException):
 code = 200
 msg = 'update ok'
 error_code = 2

class ServerError(APIException):
 code = 500
 msg = 'sorry, we made a mistake!'
 error_code = 999

class ParameterException(APIException):
 code = 400
 msg = 'invalid parameter'
 error_code = 1000

class NotFound(APIException):
 code = 404
 msg = 'the resource are not found'
 error_code = 1001

class AuthFailed(APIException):
 code = 401
 msg = 'authorization failed'
 error_code = 1005

class Forbidden(APIException):
 code = 403
 error_code = 1004
 msg = 'forbidden, not in scope'

有了這些自定義的錯誤類,我們不僅可以直接在需要的地方拋出,而且有了自定義的錯誤碼,發(fā)生錯誤時,只要對照錯誤碼去查找對應(yīng)的錯誤類,非常方便。而且特別說明的是,雖然說是錯誤類,但是也是可以定義響應(yīng)成功的返回的,比如上面定義的200,201的類,同樣可以作為一個成功的返回。

使用演示:

user = User.query.first()
if not user:
 raise NotFound()

五、注意事項

盡管我們可以在我們認為可能出錯的所有地方,繼承自己的異常類,定義自己的錯誤類,然后拋出,但是也不是所有的異常都是我們可以提前預(yù)知的。比如我們接受前端傳來的參數(shù),參數(shù)類型或取值范圍不正確,這些我們可以預(yù)知并處理好,但是如果是邏輯處理中出現(xiàn)了問題,這些不是我們程序員可以控制并處理。所以光有自定義錯誤類還不夠,我們還需要在全局捕獲異常來判斷,利用AOP思想。

# 全局錯誤AOP處理
@app.errorhandler(Exception)
def framework_error(e):
 api_logger.error("error info: %s" % e) # 對錯誤進行日志記錄
 if isinstance(e, APIException):
  return e
 if isinstance(e, HTTPException):
  code = e.code
  msg = e.description
  error_code = 1007
  return APIException(msg, code, error_code)
 else:
  if not app.config['DEBUG']:
return ServerError()
  else:
return e

這里對于flask中拋出的所有的錯誤進行捕獲,然后先進行日志的記錄。然后判斷如果是我們自定義的APIException,就直接返回。如果不是我們自定義的,但是是flask處理的HTTPException,包裝成我們自定義的APIException再返回。如果都不是的話,說明是服務(wù)器出現(xiàn)的其他錯誤,問題一般出在我們的代碼上,在生產(chǎn)環(huán)境下,一般統(tǒng)一返回一個500錯誤,在調(diào)試模式下,可以原樣返回,便于我們定位修改自己的代碼。

以上就是詳解Flask開發(fā)技巧之異常處理的詳細內(nèi)容,更多關(guān)于Flask異常處理的資料請關(guān)注本站其它相關(guān)文章!

香港服務(wù)器租用

版權(quán)聲明:本站文章來源標注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場,如有內(nèi)容涉嫌侵權(quán),請聯(lián)系alex-e#qq.com處理。

相關(guān)文章

實時開通

自選配置、實時開通

免備案

全球線路精選!

全天候客戶服務(wù)

7x24全年不間斷在線

專屬顧問服務(wù)

1對1客戶咨詢顧問

在線
客服

在線客服:7*24小時在線

客服
熱線

400-630-3752
7*24小時客服服務(wù)熱線

關(guān)注
微信

關(guān)注官方微信
頂部