異常處理
統一捕獲處理異常,使得代碼更加完善,健壯。
框架內置了一些異常,當然也可以自己定義異常然后捕獲處理。
完全可以參考官網(超喜歡這種風格的文檔):
https://fastapi.tiangolo.com/tutorial/handling-errors/
異常捕獲
在FastAPI中,最常見的就是請求參數驗證異常處理,因為FastAPI全面使用了pydantic來做數據類型校驗,所以最常見的異常就是ValidationError , 然后FastAPI繼承了這個錯誤,專門捕獲請求參數異常的RequestValidationError
捕獲異常的語法
from fastapi.exceptions import RequestValidationError
@app.exception_handler(RequestValidationError)
async def request_validation_exception_handler(request: Request, exc: RequestValidationError):
"""
請求參數驗證異常
:param request: 請求頭信息
:param exc: 異常對象
:return:
"""
# 日志記錄異常詳細上下文
logger.error(f"全局異\n{request.method}URL{request.url}\nHeaders:{request.headers}\n{traceback.format_exc()}")
return response_code.resp_422(message=exc.errors())
自定義異常
我是這樣做的,在utils/custom_exc.py文件下定義好各種異常
class UserTokenError(Exception):
def __init__(self, err_desc: str = "用戶認證異常"):
self.err_desc = err_desc
class UserNotFound(Exception):
def __init__(self, err_desc: str = "沒有此用戶"):
self.err_desc = err_desc
拋出自定異常
先倒入異常,然后raise拋出
from utils import custom_exc
# xxxx
raise custom_exc.UserTokenError(err_desc="access token fail")
捕獲自定異常
這個和內置異常捕獲語法是一樣的
@app.exception_handler(UserTokenError)
async def user_token_exception_handler(request: Request, exc: UserTokenError):
"""
用戶token異常
:param request:
:param exc:
:return:
"""
logger.error(f"用戶認證異常\nURL:{request.url}\nHeaders:{request.headers}\n{traceback.format_exc()}")
return response_code.resp_5000(message=exc.err_desc)
注冊異常
一般項目中會捕獲各種異常, 最好就是把異常函數集中起來,我是模仿Flask框架來寫的,所以FastAPI捕獲異常語法也類似
def create_app():
"""
生成FatAPI對象
:return:
"""
app = FastAPI()
# 其余的一些全局配置可以寫在這里 多了可以考慮拆分到其他文件夾
# 跨域設置
# register_cors(app)
# 注冊路由
# register_router(app)
# 注冊捕獲全局異常
register_exception(app)
# 請求攔截
# register_middleware(app)
return app
def register_static_file(app: FastAPI) -> None:
# 自定義異常 捕獲
@app.exception_handler(UserNotFound)
async def user_not_found_exception_handler(request: Request, exc: UserNotFound):
"""
用戶認證未找到
:param request:
:param exc:
:return:
"""
logger.error(f"token未知用戶\nURL:{request.url}\nHeaders:{request.headers}\n{traceback.format_exc()}")
return response_code.resp_5001(message=exc.err_desc)
# 捕獲全部異常
@app.exception_handler(Exception)
async def all_exception_handler(request: Request, exc: Exception):
"""
全局所有異常
:param request:
:param exc:
:return:
"""
logger.error(f"全局異常\n{request.method}URL:{request.url}\nHeaders:{request.headers}\n{traceback.format_exc()}")
return response_code.resp_500(message="服務器內部錯誤")
異常詳情
上一章博客有提過,使用traceback打印詳細異常
import traceback
logger.error(traceback.format_exc())
總結
以上就是最基本的捕獲異常的寫法,捕獲好異常,可以幫助更快更友好的排錯,是接口返回格式更加規范。
注意 捕獲異常函數別手誤寫錯了,多加個s, 寫成@app.exception_handlers,就會報如下異常
@app.exception_handlers(UserTokenError)
TypeError: 'dict' object is not callable
對應代碼Github地址
見個人網站 https://www.charmcode.cn/article/2020-07-19_fastapi_exception
