7. Asyncio 任务的创建和运行¶
7. Create and Run Asyncio Tasks
您可以从 asyncio 程序中的协程创建任务对象。
任务提供独立调度和运行的协程的句柄,并允许查询、取消任务以及稍后检索结果和异常。
asyncio 事件循环管理任务。 因此,所有协程都成为事件循环中的任务并作为任务进行管理。
让我们仔细看看异步任务。
You can create Task objects from coroutines in asyncio programs.
Tasks provide a handle on independently scheduled and running coroutines and allow the task to be queried, canceled, and results and exceptions to be retrieved later.
The asyncio event loop manages tasks. As such, all coroutines become and are managed as tasks within the event loop.
Let’s take a closer look at asyncio tasks.
7.1 Asyncio 任务是什么¶
7.1 What is an Asyncio Task
任务是一个调度并独立运行异步协程的对象。
它提供了预定协程的句柄,asyncio 程序可以查询该句柄并使用该句柄与协程进行交互。
任务是管理独立运行的协程的对象。
— PEP 3156 – ASYNCHRONOUS IO SUPPORT REBOOTED: THE “ASYNCIO” MODULE
任务是从协程创建的。 它需要一个协程对象,包装协程,安排其执行,并提供与其交互的方法。
任务是独立执行的。 这意味着它被调度在 asyncio 事件循环中,并且无论创建它的协程中发生了什么,它都会执行。 这与直接执行协程不同,调用者必须等待它完成。
任务用于同时调度协程。 当协程被包装到具有 asyncio.create_task() 等函数的任务中时,协程会自动安排很快运行
asyncio.Task 类扩展了 asyncio.Future 类和实例是可等待的。
Future 是一个较低级别的类,代表最终将到达的结果。
Future 是一种特殊的低级可等待对象,它表示异步操作的最终结果。
扩展 Future 类的类通常被称为类 Future 类。
运行 Python 协程的类似 Future 的对象。
因为任务是可等待的,这意味着协程可以使用等待表达式等待任务完成。
例如:
...
# 等待任务完成
await task
现在我们知道什么是异步任务,让我们看看如何创建一个异步任务。
A Task is an object that schedules and independently runs an asyncio coroutine.
It provides a handle on a scheduled coroutine that an asyncio program can query and use to interact with the coroutine.
A Task is an object that manages an independently running coroutine.
— PEP 3156 – ASYNCHRONOUS IO SUPPORT REBOOTED: THE “ASYNCIO” MODULE
A task is created from a coroutine. It requires a coroutine object, wraps the coroutine, schedules it for execution, and provides ways to interact with it.
A task is executed independently. This means it is scheduled in the asyncio event loop and will execute regardless of what else happens in the coroutine that created it. This is different from executing a coroutine directly, where the caller must wait for it to complete.
Tasks are used to schedule coroutines concurrently. When a coroutine is wrapped into a Task with functions like asyncio.create_task() the coroutine is automatically scheduled to run soon
The asyncio.Task class extends the asyncio.Future class and an instance are awaitable.
A Future is a lower-level class that represents a result that will eventually arrive.
A Future is a special low-level awaitable object that represents an eventual result of an asynchronous operation.
Classes that extend the Future class are often referred to as Future-like.
A Future-like object that runs a Python coroutine.
Because a Task is awaitable it means that a coroutine can wait for a task to be done using the await expression.
For example:
...
# wait for a task to be done
await task
Now that we know what an asyncio task is, let’s look at how we might create one.
7.2 怎么创建任务¶
7.2 How to Create a Task
使用提供的协程实例创建任务。
回想一下,协程是使用 async def 表达式定义的,看起来像一个函数。
例如:
# 定义协程
async def task_coroutine():
# ...
任务只能在协程内创建和调度。
创建和计划任务有两种主要方法,它们是:
- 使用高级 API 创建任务(首选)
- 使用低级 API 创建任务
让我们依次仔细看看每一个。
A task is created using a provided coroutine instance.
Recall that a coroutine is defined using the async def expression and looks like a function.
For example:
# define a coroutine
async def task_coroutine():
# ...
A task can only be created and scheduled within a coroutine.
There are two main ways to create and schedule a task, they are:
- Create Task With High-Level API (preferred)
- Create Task With Low-Level API
Let’s take a closer look at each in turn.
7.2.1 使用高级 API 创建任务¶
7.2.1 Create Task With High-Level API
可以使用 asyncio.create_task() 函数创建任务。
asyncio.create_task() 函数采用协程实例和任务的可选名称,并返回 asyncio.Task 实例。
例如:
...
# 创建一个协程
coro = task_coroutine()
# 从协程创建任务
task = asyncio.create_task(coro)
这可以通过单行上的复合语句来实现。
例如:
...
# 从协程创建任务
task = asyncio.create_task(task_coroutine())
这将做一些事情:
- 将协程包装在 Task 实例中。
- 安排任务在当前事件循环中执行。
- 返回一个任务实例
任务实例可以被丢弃,通过方法进行交互,并由协程等待。
这是从 asyncio 程序中的协程创建任务的首选方法。
A task can be created using the asyncio.create_task() function.
The asyncio.create_task() function takes a coroutine instance and an optional name for the task and returns an asyncio.Task instance.
For example:
...
# create a coroutine
coro = task_coroutine()
# create a task from a coroutine
task = asyncio.create_task(coro)
This can be achieved with a compound statement on a single line.
For example:
...
# create a task from a coroutine
task = asyncio.create_task(task_coroutine())
This will do a few things:
- Wrap the coroutine in a Task instance.
- Schedule the task for execution in the current event loop.
- Return a Task instance
The task instance can be discarded, interacted with via methods, and awaited by a coroutine.
This is the preferred way to create a Task from a coroutine in an asyncio program.
7.2.2 使用低级 API 创建任务¶
7.2.2 Create Task With Low-Level API
还可以使用较低级别的 asyncio API 从协程创建任务。
第一种方法是使用 asyncio.ensure_future() 函数。
此函数采用 Task、Future 或 Future-like 对象,例如协程,以及(可选)用于调度它的循环。
如果没有提供循环,它将被安排在当前的事件循环中。
如果为该函数提供了一个协程,它将被包装在一个 Task 实例中并返回。
例如:
...
# 创建并安排任务
task = asyncio.ensure_future(task_coroutine())
我们可以用来创建和调度任务的另一个低级函数是 [loop.create_task()](https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.create_task方法。
此函数需要访问特定的事件循环,在其中将协程作为任务执行。
我们可以通过 asyncio.get_event_loop() 函数获取 asyncio 程序中当前事件循环的实例。
然后可以使用它来调用 create_task() 方法来创建 Task 实例并安排其执行。
例如:
...
# 获取当前事件循环
loop = asyncio.get_event_loop()
# 创建并安排任务
task = loop.create_task(task_coroutine())
A task can also be created from a coroutine using the lower-level asyncio API.
The first way is to use the asyncio.ensure_future() function.
This function takes a Task, Future, or Future-like object, such as a coroutine, and optionally the loop in which to schedule it.
If a loop is not provided, it will be scheduled in the current event loop.
If a coroutine is provided to this function, it is wrapped in a Task instance for us, which is returned.
For example:
...
# create and schedule the task
task = asyncio.ensure_future(task_coroutine())
Another low-level function that we can use to create and schedule a Task is the loop.create_task() method.
This function requires access to a specific event loop in which to execute the coroutine as a task.
We can acquire an instance to the current event loop within an asyncio program via the asyncio.get_event_loop() function.
This can then be used to call the create_task() method to create a Task instance and schedule it for execution.
For example:
...
# get the current event loop
loop = asyncio.get_event_loop()
# create and schedule the task
task = loop.create_task(task_coroutine())
7.3 何时运行任务?¶
7.3 When Does a Task Run?
创建任务后的一个常见问题是它何时运行?
这是一个很好的问题。
虽然我们可以使用 create_task() 函数安排协程作为任务独立运行,但它可能不会立即运行。
事实上,直到事件循环有机会运行时,任务才会执行。
直到所有其他协程都没有运行并且轮到任务运行时,才会发生这种情况。
例如,如果我们有一个 asyncio 程序,其中一个协程创建并计划了一项任务,则计划的任务将不会运行,直到创建该任务的调用协程被挂起。
如果调用协程选择休眠、选择等待另一个协程或任务、或者选择等待已安排的新任务,则可能会发生这种情况。
例如:
...
# 从协程创建任务
task = asyncio.create_task(task_coroutine())
# 等待任务,允许其运行
await task
您可以在教程中了解有关如何创建异步任务的更多信息:
现在我们知道什么是任务以及如何安排它们,接下来,让我们看看如何在程序中使用它们。
A common question after creating a task is when does it run?
This is a good question.
Although we can schedule a coroutine to run independently as a task with the create_task() function, it may not run immediately.
In fact, the task will not execute until the event loop has an opportunity to run.
This will not happen until all other coroutines are not running and it is the task’s turn to run.
For example, if we had an asyncio program with one coroutine that created and scheduled a task, the scheduled task will not run until the calling coroutine that created the task is suspended.
This may happen if the calling coroutine chooses to sleep, chooses to await another coroutine or task, or chooses to await the new task that was scheduled.
For example:
...
# create a task from a coroutine
task = asyncio.create_task(task_coroutine())
# await the task, allowing it to run
await task
You can learn more about how to create asyncio tasks in the tutorial:
Now that we know what a task is and how to schedule them, next, let’s look at how we may use them in our programs.
创建日期: 2024年9月4日