这样做的方法是override the HTTPException error handler,由于exception_handler中没有BackgroundTasks对象,您可以按照Starlette documentation(FastAPI is actually Starlette underneath)中描述的方式将后台任务添加到响应中.下面的例子:
from fastapi import BackgroundTasks, FastAPI, HTTPException, Request
from fastapi.responses import PlainTextResponse
from starlette.exceptions import HTTPException as StarletteHTTPException
from starlette.background import BackgroundTask
app = FastAPI()
def write_notification(message):
with open('log.txt', 'a') as f:
f.write(f'{message}'+'
')
@app.exception_handler(StarletteHTTPException)
async def http_exception_handler(request, exc):
task = BackgroundTask(write_notification, message=exc.detail)
return PlainTextResponse(str(exc.detail), status_code=exc.status_code, background=task)
@app.get("/{msg}")
def send_notification(msg: str, background_tasks: BackgroundTasks):
if "hello" in msg:
raise HTTPException(status_code=500, detail="Something went wrong")
background_tasks.add_task(write_notification, message="Success")
return {"message": "Request has been successfully submitted."}
如果您需要add multiple background tasks to a response,则使用:
@app.exception_handler(StarletteHTTPException)
async def http_exception_handler(request, exc):
tasks = BackgroundTasks()
tasks.add_task(write_notification, message=exc.detail)
tasks.add_task(some_other_function, message="some other message")
return PlainTextResponse(str(exc.detail), status_code=exc.status_code, background=tasks)
上述方法的一种变体如下(建议here):
from starlette.background import BackgroundTask
@app.exception_handler(StarletteHTTPException)
async def http_exception_handler(request, exc):
response = PlainTextResponse(str(exc.detail), status_code=exc.status_code)
response.background = BackgroundTask(write_notification, message=exc.detail)
# or, response.background = tasks (create `tasks` as in the previous code snippet)
return response
一些可能证明对您的任务有用的参考资料是:this answer,它演示了如何添加 custom exception handlers,以及 this answer,它显示了用于传入请求和传出响应的自定义日志记录系统。