您可以定义返回响应后要运行的后台任务。
这对于在请求之后需要进行的操作很有用,但是客户端实际上并不需要在收到响应之前就等待操作完成。
例如,这包括:
执行操作后发送的电子邮件通知: 由于连接到电子邮件服务器并发送电子邮件的过程通常很慢(几秒钟),因此您可以立即返回响应并在后台发送电子邮件通知。
处理数据: 例如,假设您收到一个文件,该文件必须经过缓慢的处理,您可以返回“已接受”(HTTP 202)响应,并在后台对其进行处理。

使用后台任务

首先,导入BackgroundTasks并在路径操作函数中使用BackgroundTasks的类型声明定义一个参数:

  1. from fastapi import BackgroundTasks, FastAPI

FastAPI将为您创建BackgroundTasks类型的对象,并将其作为该参数传递。

创建一个任务函数

创建一个要作为后台任务运行的函数。
它只是可以接收参数的标准功能。
它可以是async def或普通def函数,FastAPI将知道如何正确处理它。
在这种情况下,任务功能将写入文件(模拟发送电子邮件)。由于写操作不使用asyncawait,因此我们使用普通def定义函数:

  1. from fastapi import BackgroundTasks, FastAPI
  2. app = FastAPI()
  3. def write_notification(email: str, message=""):
  4. with open("log.txt", mode="w") as email_file:
  5. content = f"notification for {email}: {message}"
  6. email_file.write(content)

添加后台任务

在路径操作函数内部,使用.add_task()方法将任务函数传递给后台任务对象:

  1. from fastapi import BackgroundTasks, FastAPI
  2. app = FastAPI()
  3. def write_notification(email: str, message=""):
  4. with open("log.txt", mode="w") as email_file:
  5. content = f"notification for {email}: {message}"
  6. email_file.write(content)
  7. @app.post("/send-notification/{email}")
  8. async def send_notification(email: str, background_tasks: BackgroundTasks):
  9. background_tasks.add_task(write_notification, email, message="some notification")
  10. return {"message": "Notification sent in the background"}

.add_task()接收作为参数:
在后台运行的任务功能(write_notification)。
应该按顺序传递给任务功能的任何参数序列(email)。
* 应该传递给任务功能的任何关键字参数(message="some notification")。

依赖注入

使用BackgroundTasks还可以与依赖项注入系统一起使用,您可以在多个级别上声明BackgroundTasks类型的参数:在路径操作函数中,在依赖项中(可依赖),在子依赖项中等等。
FastAPI知道在每种情况下该做什么,以及如何重用同一对象,以便所有后台任务合并在一起,然后在后台运行:

  1. from fastapi import BackgroundTasks, Depends, FastAPI
  2. app = FastAPI()
  3. def write_log(message: str):
  4. with open("log.txt", mode="a") as log:
  5. log.write(message)
  6. def get_query(background_tasks: BackgroundTasks, q: str = None):
  7. if q:
  8. message = f"found query: {q}\n"
  9. background_tasks.add_task(write_log, message)
  10. return q
  11. @app.post("/send-notification/{email}")
  12. async def send_notification(
  13. email: str, background_tasks: BackgroundTasks, q: str = Depends(get_query)
  14. ):
  15. message = f"message to {email}\n"
  16. background_tasks.add_task(write_log, message)
  17. return {"message": "Message sent"}

在此示例中,消息将在发送响应后写入到log.txt文件中。
如果请求中有查询,它将在后台任务中写入日志。
然后,在路径操作功能处生成的另一个后台任务将使用电子邮件路径参数编写一条消息。

详细教程

BackgroundTasks直接来自starlette.background
它直接导入/包含在FastAPI中,因此您可以从fastapi导入它,避免从starlette.background意外导入替代BackgroundTask(末尾没有s)。
通过仅使用BackgroundTasks(而不是BackgroundTask),就可以将其用作路径操作函数参数,并让FastAPI为您处理其余部分,就像直接使用Request对象一样。
在FastAPI中仍然可以单独使用BackgroundTask,但是您必须在代码中创建对象,然后返回包含它的Starlette Response
您可以在Starlette的“后台任务”官方文档中查看更多详细信息。

警告

如果您需要执行大量的后台计算,而不必一定要在同一进程中运行它(例如,您不需要共享内存,变量等),则可能会受益于使用其他更大的工具,例如Celery
它们往往需要更复杂的配置,例如RabbitMQ或Redis等消息/作业队列管理器,但是它们允许您在多个进程(尤其是多个服务器)中运行后台任务。
要查看示例,请检查项目生成器,它们都包括已经配置的Celery。
但是,如果您需要从同一个FastAPI应用程序访问变量和对象,或者需要执行一些小的后台任务(例如发送电子邮件通知),则只需使用BackgroundTasks

概括

导入并使用BackgroundTasks及其路径操作函数和相关性中的参数来添加后台任务。