FastAPI--错误处理(5)
一、概述
HTTPException异常抛出
再之前Bottle 中其实有一个就是HttpError异常类,在FastAPI也存在这么一个HTTPException。比如:
import uvicorn from fastapi import FastAPI, HTTPException app = FastAPI() items = {"foo": "The Foo Wrestlers"} @app.get("/items/{item_id}") async def read_item(item_id: str): if item_id not in items: raise HTTPException(status_code=404, detail="Item not found") return {"item": items[item_id]} if __name__ == '__main__': uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
在上面的代码中,通过判断item_id是不是存在于items来主动的抛出了一个404的错误
访问一个错误的url
http://127.0.0.1:8000/items/asda
我们查看HTTPException和StarletteHTTPException的源码发现他们也是继承与Exception:
class HTTPException(StarletteHTTPException): def __init__( self, status_code: int, detail: Any = None, headers: dict = None ) -> None: super().__init__(status_code=status_code, detail=detail) self.headers = headers
所以我们对于异常通常可以直接的使用 raise来抛出异常。
HTTPException且返回新增自定义请求头
import uvicorn from fastapi import FastAPI, HTTPException app = FastAPI() items = {"foo": "The Foo Wrestlers"} @app.get("/items-header/{item_id}") async def read_item_header(item_id: str): if item_id not in items: raise HTTPException( status_code=404, detail="Item not found", headers={"X-Error": "There goes my error"}, ) return {"item": items[item_id]} if __name__ == '__main__': uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
访问一个错误的url
http://127.0.0.1:8000/items-header/asda
查看Headers,发现多了X-Error
自定义返回HTTPException
类似之前Bottle我们通过添加一个自定义的全局的错误,来统一的处理返回。FastAPI其实也提供一个自定义错误的机制:
官方示例如下:
import uvicorn from fastapi import FastAPI, Request from fastapi.responses import JSONResponse class UnicornException(Exception): def __init__(self, name: str): self.name = name app = FastAPI() @app.exception_handler(UnicornException) async def unicorn_exception_handler(request: Request, exc: UnicornException): return JSONResponse( status_code=418, content={"message": f"Oops! {exc.name} did something. There goes a rainbow..."}, ) @app.get("/unicorns/{name}") async def read_unicorn(name: str): if name == "yolo": raise UnicornException(name=name) return {"unicorn_name": name} if __name__ == '__main__': uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
观察请求结果:
http://127.0.0.1:8000/unicorns/yolo
当请求name == yolo的时候,我们主动抛出了UnicornException,而且我们,@app.exception_handler(UnicornException)也捕获到相关的异常信息,且返回了相关的信息。
覆盖FastAPI默认的异常处理
按官方文档说明就是,当请求包含无效的数据的时候,或参数提交异常错误的时候,会抛出RequestValidationError,
那其实我也可以通过上面的自定义异常的方式来覆盖重写我们的RequestValidationError所返回信息:
如: 默认代码没有添加覆盖处理的话: 发生异常的时候是提示是:
import uvicorn from fastapi import FastAPI, HTTPException from fastapi.exceptions import RequestValidationError from fastapi.responses import PlainTextResponse from starlette.exceptions import HTTPException as StarletteHTTPException from fastapi.responses import JSONResponse app = FastAPI() @app.exception_handler(StarletteHTTPException) async def http_exception_handler(request, exc): return PlainTextResponse(str(exc.detail), status_code=exc.status_code) # @app.exception_handler(RequestValidationError) # async def validation_exception_handler(request, exc): # return JSONResponse({'mes':'触发了RequestValidationError错误,,错误信息:%s 你妹的错了!'%(str(exc))}) @app.get("/items/{item_id}") async def read_item(item_id: int): if item_id == 3: raise HTTPException(status_code=418, detail="Nope! I don't like 3.") return {"item_id": item_id} if __name__ == '__main__': uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
发生异常的请求下返回:
http://127.0.0.1:8000/items/yolo
恢复覆盖的时候:
import uvicorn from fastapi import FastAPI, HTTPException from fastapi.exceptions import RequestValidationError from fastapi.responses import PlainTextResponse from starlette.exceptions import HTTPException as StarletteHTTPException from fastapi.responses import JSONResponse app = FastAPI() @app.exception_handler(StarletteHTTPException) async def http_exception_handler(request, exc): return PlainTextResponse(str(exc.detail), status_code=exc.status_code) @app.exception_handler(RequestValidationError) async def validation_exception_handler(request, exc): return JSONResponse({'mes':'触发了RequestValidationError错误,,错误信息:%s 你妹的错了!'%(str(exc))}) @app.get("/items/{item_id}") async def read_item(item_id: int): if item_id == 3: raise HTTPException(status_code=418, detail="Nope! I don't like 3.") return {"item_id": item_id} if __name__ == '__main__': uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
请求结果:
上面的返回其实我们还可以修改一下返回如下,指定响应码:
import uvicorn from fastapi import FastAPI, HTTPException from fastapi.exceptions import RequestValidationError from fastapi.responses import PlainTextResponse from starlette.exceptions import HTTPException as StarletteHTTPException from fastapi.responses import JSONResponse from fastapi import FastAPI, Request,status from fastapi.encoders import jsonable_encoder app = FastAPI() @app.exception_handler(StarletteHTTPException) async def http_exception_handler(request, exc): return PlainTextResponse(str(exc.detail), status_code=exc.status_code) @app.exception_handler(RequestValidationError) async def validation_exception_handler(request: Request, exc: RequestValidationError): return JSONResponse( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, content=jsonable_encoder({"detail": exc.errors(), "body": exc.body}), ) @app.get("/items/{item_id}") async def read_item(item_id: int): if item_id == 3: # 注意fastapi包中的HTTPException才可以定义请求头 raise HTTPException(status_code=418, detail="Nope! I don't like 3.") return {"item_id": item_id} if __name__ == '__main__': uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
再次请求一下
可以发现状态码是指定的422,返回信息也是指定的。
本文参考链接:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
2019-06-12 Ubuntu /etc/security/limits.conf 不生效问题
2018-06-12 python 全栈开发,Day61(库的操作,表的操作,数据类型,数据类型(2),完整性约束)