FastAPI 教程翻译 - 用户指南 31 - 后台任务
FastAPI Tutorial - User Guide - Background Tasks
You can define background tasks to be run after returning a response.
您可以定义要在返回响应后运行的后台任务。
This is useful for operations that need to happen after a request, but that the client doesn’t really have to be waiting for the operation to complete before receiving his response.
这对于在请求之后需要进行的操作很有用,但是客户端实际上并不需要在收到响应之前就等待操作完成。
This includes, for example:
这包括,例如:
-
Email notifications sent after performing an action:
执行操作后发送的电子邮件通知:
-
As connecting to an email server and sending an email tends to be “slow” (several seconds), you can return the response right away and send the email notification in the background.
由于连接到电子邮件服务器并发送电子邮件的过程通常很慢(几秒钟),因此您可以立即返回响应并在后台发送电子邮件通知。
-
-
Processing data:
处理数据:
-
For example, let’s say you receive a file that must go through a slow process, you can return a response of “Accepted” (HTTP 202) and process it in the background.
例如,假设您收到的文件必须经过缓慢的处理,您可以返回『已接受』(HTTP 202)响应,并在后台对其进行处理。
-
Using BackgroundTasks
使用 BackgroundTasks
First, import BackgroundTasks
and define a parameter in your path operation function with a type declaration of BackgroundTasks
:
首先,导入 BackgroundTasks
并在路径操作函数中定义一个带有 BackgroundTasks
类型声明的参数:
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"}
FastAPI will create the object of type BackgroundTasks
for you and pass it as that parameter.
FastAPI 将为您创建 BackgroundTasks
类型的对象,并将其作为该参数传递。
Create a task function
创建任务功能
Create a function to be run as the background task.
创建一个要作为后台任务运行的函数。
It is just a standard function that can receive parameters.
它只是可以接收参数的标准功能。
It can be an async def
or normal def
function, FastAPI will know how to handle it correctly.
它可以是一个 async def
或普通的 def
功能,FastAPI 会知道如何正确处理它。
In this case, the task function will write to a file (simulating sending an email).
在这种情况下,任务功能将写入文件(模拟发送电子邮件)。
And as the write operation doesn’t use async
and await
, we define the function with normal def
:
由于写操作不使用 async
和 await
,我们用普通的 def
定义了该函数:
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 the background task
添加后台任务
Inside of your path operation function, pass your task function to the background tasks object with the method .add_task()
:
在您的路径操作函数内部,使用 .add_task()
方法将您的任务函数传递给后台对象:
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()
receives as arguments:
.add_task()
接收作为参数:
-
A task function to be run in the background (
write_notification
).任务功能在后台运行(
write_notification
)。 -
Any sequence of arguments that should be passed to the task function in order (
email
).应该按顺序传递到任务功能的任何参数序列(
email
)。 -
Any keyword arguments that should be passed to the task function (
message="some notification"
).应该传递给任务功能的任何关键字参数(
message="some notification"
)。
Dependency Injection
依赖注入
Using BackgroundTasks
also works with the dependency injection system, you can declare a parameter of type BackgroundTasks
at multiple levels: in a path operation function, in a dependency (dependable), in a sub-dependency, etc.
使用 BackgroundTasks
还可以与依赖项注入系统一起使用,您可以在多个级别上声明 BackgroundTasks
类型的参数:在路径操作函数中,在依赖项中(被依赖项),在子依赖项中,等等。
FastAPI knows what to do in each case and how to re-use the same object, so that all the background tasks are merged together and are run in the background afterwards:
FastAPI 知道每种情况下的操作以及如何重用同一对象,以便所有后台任务合并在一起并在后台运行:
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: str = None):
if q:
message = f"found query: {q}\n"
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}\n"
background_tasks.add_task(write_log, message)
return {"message": "Message sent"}
In this example, the messages will be written to the log.txt
file after the response is sent.
在此示例中,消息将在发送响应之后被写入 log.txt
文件中。
If there was a query in the request, it will be written to the log in a background task.
如果请求中有查询,它将在后台任务中写入日志。
And then another background task generated at the path operation function will write a message using the email
path parameter.
然后,在路径操作函数处生成的另一个后台任务将使用 email
路径参数写入一条消息。
Technical Details
技术细节
The class BackgroundTasks
comes directly from starlette.background
.
类 BackgroundTasks
直接来自 starlette.background
。
It is imported/included directly into FastAPI so that you can import it from fastapi
and avoid accidentally importing the alternative BackgroundTask
(without the s
at the end) from starlette.background
.
它直接导入 / 包含在 FastAPI 中,因此您可以从 fastapi
导入它,避免从 starlette.background
意外导入替代的 BackgroundTask
(末尾没有s)。
By only using BackgroundTasks
(and not BackgroundTask
), it’s then possible to use it as a path operation function parameter and have FastAPI handle the rest for you, just like when using the Request
object directly.
仅使用 BackgroundTasks
(而不是 BackgroundTask
),就可以将其用作路径操作函数参数,并让 FastAPI 为您处理其余部分,就像使用 Request
对象时一样直接。
It’s still possible to use BackgroundTask
alone in FastAPI, but you have to create the object in your code and return a Starlette Response
including it.
在 FastAPI 中仍然可以单独使用 BackgroundTask
,但是您必须在代码中创建对象并返回包含它的 Starlette Response
。
You can see more details in Starlette’s official docs for Background Tasks.
您可以在 Starlette的后台任务官方文档 中查看更多详细信息。
Caveat
警告
If you need to perform heavy background computation and you don’t necessarily need it to be run by the same process (for example, you don’t need to share memory, variables, etc), you might benefit from using other bigger tools like Celery.
如果您需要执行大量的后台计算,而不必一定要在同一进程中运行它(例如,您不需要共享内存,变量等),则可能会受益于使用其他更大的工具,例如 Celery。
They tend to require more complex configurations, a message/job queue manager, like RabbitMQ or Redis, but they allow you to run background tasks in multiple processes, and especially, in multiple servers.
它们往往需要更复杂的配置,例如 RabbitMQ 或 Redis 之类的消息/作业队列管理器,但是它们允许您在多个进程(尤其是多个服务器)中运行后台任务。
To see an example, check the Project Generators, they all include Celery already configured.
要查看示例,请查看 Project Generators,它们都包含已经配置的 Celery。
But if you need to access variables and objects from the same FastAPI app, or you need to perform small background tasks (like sending an email notification), you can simply just use BackgroundTasks
.
但是,如果您需要从同一个 FastAPI 应用程序访问变量和对象,或者需要执行一些小的后台任务(例如发送电子邮件通知),则只需使用 BackgroundTasks
即可。
Recap
回顾
Import and use BackgroundTasks
with parameters in path operation functions and dependencies to add background tasks.
导入并使用 BackgroundTasks
及其在路径操作函数中的参数以及相关性来添加后台任务。