###### tags: `Flask`
# Python Flask API 例外處理
* 概念:
* 在API的function前方加上@exception_handler裝飾器,功能邏輯需要return錯誤的時候,就直接raise自定義的exception。
* 所有例外要回傳的訊息統一用exception_hadler管理。
* 另外可以在自定義例外類別,客製化例外訊息、http status、error code。
## API
```python=3
from utils.exception_handler import exception_handler
@app.route('/user', methods=['POST'])
@exception_handler
def user_create():
api_key = request.headers.get('api-key')
if api_key != customer_api_key:
raise ApiHeaderAuthError()
# raise ApiHeaderAuthError(message="other info", info="other info", code="error-001", status=501)
data = request.json
identity = data['identity']
friendly_name = data['friendly_name']
client.conversations.services(service_id).users.create(identity=identity, friendly_name=friendly_name, attributes=data)
return jsonify({"message": "user created successfully"})
```
## utils.exception_handler
```python=
import sys
import traceback
from functools import wraps
from flask import jsonify
from twilio.base.exceptions import TwilioRestException
from utils.exceptions import *
"""
抓取父類的例外,可以連同繼承此父類的例外都擷取到。
"""
def exception_handler(func):
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except TwilioRestException as e:
return jsonify({"info": str(e.msg)}), e.status
except ApiError as e:
# print(e.__class__.__name__) # 可以查看例外子類class名稱
return {"code": e.code, "message": e.message, "info": e.info}, e.status
except KeyError as e:
return {"message": "key error", "info": str(e)}, 400
except Exception as e:
traceback.print_tb(sys.exc_info()[2])
return {"message": "Something wrong", "info": str(e)}, 500
return wrapper
```
## utils.exceptions
```python=
class ApiError(Exception):
""" A generic 400 or 500 level exception from the Twilio API
:param str|None message: A human-readable brief message for the error
:param str|None info: Detail information about the error
:param str|None code: A self-defined error code for the error
:param int|500 status: the HTTP status that was returned for the exception
"""
def __init__(self, message=None, info=None, code=None, status=500):
self.message = message
self.info = info
self.code = code
self.status = status
def __str__(self):
return self.message
class ApiHeaderAuthError(ApiError):
def __init__(self, message="Header auth failed.", info=None, code=None, status=401):
super().__init__(message, info, code, status)
```
###### tag: `Flask` `exception`