乐趣区

关于程序员:Python-异步-当前和正在运行的任务9

咱们能够检查在 asyncio 事件循环中运行的工作。这能够通过为以后运行的工作和所有正在运行的工作获取一个 asyncio.Task 对象来实现。

1. 如何获取当前任务

咱们能够通过 asyncio.current_task() 函数获取当前任务。此函数将为以后正在运行的工作返回一个工作对象。

...
# get the current task
task = asyncio.current_task()

这将为以后正在运行的工作返回一个工作对象。这可能是:

  1. 传递给 asyncio.run() 的主协程。
  2. 通过 asyncio.create_task() 在 asyncio 程序中创立和调度的工作。

一个工作能够创立并运行另一个协程(例如,不蕴含在工作中)。从协程中获取当前任务将为正在运行的工作返回一个 Task 对象,但不会返回以后正在运行的协程。

如果协程或工作须要无关本身的详细信息,例如用于日志记录的工作名称,则获取当前任务会很有帮忙。

咱们能够摸索如何为用于启动 asyncio 程序的主协程获取 Task 实例。上面的示例定义了一个用作程序入口点的协程。它报告一条音讯,而后获取当前任务并报告其详细信息。

这是第一个重要的示例,因为它强调所有协程都能够作为异步事件循环中的工作进行拜访。

上面列出了残缺的示例。

# SuperFastPython.com
# example of getting the current task from the main coroutine
import asyncio
 
# define a main coroutine
async def main():
    # report a message
    print('main coroutine started')
    # get the current task
    task = asyncio.current_task()
    # report its details
    print(task)
 
# start the asyncio program
asyncio.run(main())

运行该示例首先创立主协程并应用它来启动 asyncio 程序。main() 协程运行并首先报告一条音讯。

而后它检索当前任务,这是一个代表本身的工作对象,即以后正在运行的协程。而后它会报告以后正在运行的工作的详细信息。

咱们能够看到该工作具备第一个工作的默认名称“Task-1”,并且正在执行 main() 协程,即以后正在运行的协程。

这突出表明咱们能够应用 asyncio.current_task() 函数来拜访以后正在运行的协程的工作对象,该对象主动包装在工作对象中。

main coroutine started
<Task pending name='Task-1' coro=<main() running at ...> cb=[_run_until_complete_cb() at ...]>

2. 如何获取所有工作

咱们可能须要拜访异步程序中的所有工作。这可能有很多起因,例如:

  • 检查程序的以后状态或复杂性。
  • 记录所有正在运行的工作的详细信息。
  • 查找能够查问或勾销的工作。

咱们能够通过 asyncio.all_tasks() 函数在 asyncio 程序中获取一组所有已打算和正在运行(尚未实现)的工作。

...
# get all tasks
tasks = asyncio.all_tasks()

这将返回 asyncio 程序中所有工作的汇合。它是一个汇合,因而每个工作只代表一次。

如果呈现以下状况,将包含一项工作:

  1. 工作已安顿但尚未运行。
  2. 该工作以后正在运行(例如,但以后已暂停)

该汇合还将包含以后正在运行的工作的工作,例如正在执行调用 asyncio.all_tasks() 函数的协程的工作。

另外,回忆一下用于启动 asyncio 程序的 asyncio.run() 办法会将提供的协程包装在工作中。这意味着所有工作的汇合将包含程序入口点的工作。

咱们能够摸索在一个 asyncio 程序中有很多工作的状况,而后失去一组所有工作。

在此示例中,咱们首先创立 10 个工作,每个工作包装并运行雷同的协程。主协程而后获取程序中打算或运行的所有工作的汇合并报告它们的详细信息。

上面列出了残缺的示例。

# SuperFastPython.com
# example of starting many tasks and getting access to all tasks
import asyncio
 
# coroutine for a task
async def task_coroutine(value):
    # report a message
    print(f'task {value} is running')
    # block for a moment
    await asyncio.sleep(1)
 
# define a main coroutine
async def main():
    # report a message
    print('main coroutine started')
    # start many tasks
    started_tasks = [asyncio.create_task(task_coroutine(i)) for i in range(10)]
    # allow some of the tasks time to start
    await asyncio.sleep(0.1)
    # get all tasks
    tasks = asyncio.all_tasks()
    # report all tasks
    for task in tasks:
        print(f'> {task.get_name()}, {task.get_coro()}')
    # wait for all tasks to complete
    for task in started_tasks:
        await task
 
# start the asyncio program
asyncio.run(main())

运行该示例首先创立主协程并应用它来启动 asyncio 程序。main() 协程运行并首先报告一条音讯。而后它创立并安顿 10 个包装自定义协程的工作。而后 main() 协程会阻塞片刻以容许工作开始运行。工作开始运行,每个工作报告一条音讯,而后休眠。

main() 协程复原并获取程序中所有工作的列表。而后它报告每个的名称和协程。最初,它枚举已创立的工作列表并期待每个工作实现。

这突出表明咱们能够取得 asyncio 程序中所有工作的汇合,其中包含创立的工作以及代表程序入口点的工作。

main coroutine started
task 0 is running
task 1 is running
task 2 is running
task 3 is running
task 4 is running
task 5 is running
task 6 is running
task 7 is running
task 8 is running
task 9 is running
> Task-9, <coroutine object task_coroutine at 0x10e186e30>
> Task-2, <coroutine object task_coroutine at 0x10e184e40>
> Task-11, <coroutine object task_coroutine at 0x10e186f10>
> Task-7, <coroutine object task_coroutine at 0x10e186d50>
> Task-4, <coroutine object task_coroutine at 0x10e185700>
> Task-10, <coroutine object task_coroutine at 0x10e186ea0>
> Task-8, <coroutine object task_coroutine at 0x10e186dc0>
> Task-5, <coroutine object task_coroutine at 0x10e186ab0>
> Task-1, <coroutine object main at 0x10e1847b0>
> Task-3, <coroutine object task_coroutine at 0x10e184f90>
> Task-6, <coroutine object task_coroutine at 0x10e186ce0>

接下来,咱们将探讨如何同时运行多个协程。

退出移动版