FastAPI系列:FastAPI中全局异常处理
HTTPException介绍
HTTPException是FastAPI中用于处理HTTP错误的异常类。当你在处理请求时遇到异常情况,可以抛出HTTPException,
FastAPI将自动使用合适的HTTP状态码和响应体返回给客户端。以下是一些详细的说明:
- HTTPException是一个派生自BaseException的异常类,但它同时可以把异常信息作为HttpResponse返回。
- HTTPException是一个常规的Python异常,但是它包含了额外的和API相关的数据。因为它是一个Python异常,你不返回它,你抛出它。
- 当你在路由中,甚至在简单的业务代码中也可以raise一个HTTPException或者是派生至HTTPException的异常,从而向endpoint用户传递友好的异常信息。
- 当客户端请求一个不存在的item时,触发状态码为404的异常:raise HTTPException(status_code=404, detail="Item not found")
装饰器版本自定义异常
1.首先我们定义三个文件,分别为exception.py,main.py, user.py
2.自定义异常需要继承HTTPException,该异常可以从fastapi中直接导入
from fastapi import HTTPException
3.exception.py中定义我们业务模块的异常
from fastapi import HTTPException
class UserDoesNotExistsException(HTTPException):
def __init__(self, detail: str, status_code: int):
self.detail = detail
self.status_code = status_code
4. user.py文件
router_user = APIRouter(prefix='/user', tags=['用户模块'])
@router_user.get('/{user_id}')
async def get_id_by_user(user_id: int):
if user_id != 1:
raise UserDoesNotExistsException(status_code=400, detail="id not exists")
return {"user_id": user_id}
5.main.py文件
from fastapi import FastAPI
from exception import UserDoesNotExistsException
from user import router_user
app = FastAPI(debug=True)
# 这里就是添加使用我们自定义的错误处理
@app.exception_handler(UserDoesNotExistsException)
def user_exception_handler(req: Request, ex: UserDoesNotException):
return JSONResponse(
status_code=ex.status_code,
content={"message": f'error: {ex.detail}'}
)
app.include_router(router_user, prefix='/api/v1')
非装饰器版
第一种,通过在FastAPI()中指定exception_handlers
from fastapi import FastAPI
from fastapi.responses import JSONResponse
async def exception_not_found(request, exc):
return JSONResponse({
'code':exc.status_code,
'error':'not found',
status_code=exc.status_code
})
exception_handlers = {
# 键值对的形式,写具体的状态码或者具体的Exception子类都可以,后面完整例子中有
404: exception_not_found,
}
app = FastAPI(exception_handlers=exception_handlers)
第二种,通过实例化的FastAPI对象的add_exception_handler方法
from fastapi import FastAPI
from fastapi.responses import JSONResponse
async def exception_not_found(request, exc):
return JSONResponse({
'code':exc.status_code,
'error':'not found',
status_code=exc.status_code
})
app = FastAPI()
# 同理,可以写具体的状态码或者具体的Exception子类都可以
app.add_exception_handler(404, exception_not_found)
完整案例,项目中可以使用
1.定义四个文件,exception.py(全局处理), main.py(主程序文件), user/user.py(业务模块), user/exception.py(用户模块自己的错误处理)
2.exception.py文件
# from fastapi.exceptions import HTTPException
from starlette.exceptions import HTTPException # 官方推荐注册异常处理器时,应该注册到来自 Starlette 的 HTTPException
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
# 全局异常
async def global_exception_handler(request, exc):
if exc.status_code == 500:
err_msg = 'Server Internal Error'
else:
err_msg = exc.detail
return JSONResponse({
'code': exc.status_code,
'err_msg': err_msg,
'status': 'Failed'
})
# 请求数据无效时的错误处理
"""
example: http://127.0.0.1/user/{user_id}
success: http://127.0.0.1/user/1
failed: http://127.0.0.1/user/d
"""
async def validate_exception_handler(request, exc):
err = exc.errors()[0]
return JSONResponse({
'code': 400,
'err_msg': err['msg'],
'status': 'Failed'
})
golbal_exception_handlers = {
HTTPException: global_exception_handler,
RequestValidationError: validate_exception_handler
}
class BaseAPIException(HTTPException):
status_code = 400
detail = 'api error'
def __init__(self, detail: str = None, status_code: int = None):
self.detail = detail or self.detail
self.status_code = status_code or self.status_code
3.定义user/exception.py
from exception import BaseAPIException
class UserDoesNotExistsException(BaseAPIException):
status_code = 10000
detail = 'user does not exists'
4.定义uers/user.py
from fastapi.routing import APIRouter
from .exception import UserDoesNotExistsException
router_user = APIRouter(prefix='/user', tags=['用户模块'])
@router_user.get("/{user_id}")
async def get_id_by_user(user_id: int):
if user_id != 1:
# 这里使用我们自定义的用户错误处理
# 返回的统一响应格式{"code":10000,"err_msg":"user does not exists","status":"Failed"}
raise UserDoesNotExistsException
return {"user_id": user_id}
5.定义main.py
from fastapi import FastAPI
from exception import golbal_exception_handlers
from user.user import router_user
app = FastAPI(debug=True, exception_handlers=golbal_exception_handlers)
app.include_router(router_user, prefix='/api/v1')
if __name__ == '__main__':
import uvicorn
uvicorn.run(app='main:app', host='0.0.0.0', port=9002, reload=True)
6.响应
# example: http://127.0.0.1:9002/api/v1/user/2
{"code":10000,"err_msg":"user does not exists","status":"Failed"}
# example: http://127.0.0.1:9002/api/v1/user/d
{"code":400,"err_msg":"value is not a valid integer","status":"Failed"}
-------------------------------------------
个性签名:代码过万,键盘敲烂!!!
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!