作者:麦克煎蛋   出处:https://www.cnblogs.com/mazhiyong/ 转载请保留这段声明,谢谢!

有时候我们需要在request执行之后继续一些操作,但终端并不需要等待这些操作完成才能收到response。

其中一些场景举例如下:

1、在执行完request之后发送邮件通知。

2、收到文件之后对文件进行二次处理。

这些操作都需要一定的处理时间,但与返回给终端的response并无直接关系。

我们可以通过定义后台任务BackgroundTasks,来实现这个功能。

使用 BackgroundTasks

首先我们需要导入BackgroundTasks,并在路径操作函数中添加BackgroundTasks类型的参数。

from fastapi import BackgroundTasks, FastAPI

app = FastAPI()


@app.post("/send-notification/{email}")
async def send_notification(email: str, background_tasks: BackgroundTasks):
  pass

任务函数

然后我们需要创建一个在后台任务中实际执行的函数:任务函数。

这是一个标准函数。这个函数可以是async def或者普通def的函数。

这里我们创建一个把指定内容写入文件的函数。

def write_notification(email: str, message=""):
    with open("log.txt", mode="w") as email_file:
        content = f"notification for {email}: {message}"
        email_file.write(content)

添加后台任务

最后我们需要把任务函数添加到后台任务中去。

from fastapi import BackgroundTasks, FastAPI

app = FastAPI()


def write_notification(email: str, message=""):
    with open("log.txt", mode="w") as email_file:
        content = f"notification for {email}: {message}"
        email_file.write(content)


@app.post("/send-notification/{email}")
async def send_notification(email: str, background_tasks: BackgroundTasks):
    background_tasks.add_task(write_notification, email, message="some notification")
return {"message": "Notification sent in the background"}

.add_task()接收以下参数信息:

在后台运行的任务函数(例如 write_notification)
任意序列的参数信息(例如 email)
任意键值对的参数信息(例如 message="some notification")

依赖注入

后台任务可以与依赖注入系统一起使用,我们可以在不同层级的依赖项中声明BackgroundTasks参数。

from typing import Optional
from fastapi import BackgroundTasks, Depends, FastAPI

app = FastAPI()


def write_log(message: str):
    with open("log.txt", mode="a") as log:
        log.write(message)


def get_query(background_tasks: BackgroundTasks, q: Optional[str] = None):
if q:
  message = f"found query: {q}
" background_tasks.add_task(write_log, message)
return q


@app.post("/send-notification/{email}")
async def send_notification(email: str, background_tasks: BackgroundTasks, q: str = Depends(get_query)):
    message = f"message to {email}
" background_tasks.add_task(write_log, message)
return {"message": "Message sent"}