乐趣区

关于程序员:Python-异步-同时运行多个协程10

asyncio 的一个益处是咱们能够同时运行许多协程。这些协同程序能够在一个组中创立并存储,而后同时一起执行。这能够应用 asyncio.gather() 函数来实现。

让咱们认真看看。

1. 什么是 Asyncio gather()

asyncio.gather() 模块函数容许调用者将多个可期待对象组合在一起。分组后,可期待对象能够并发执行、期待和勾销。

它是一个有用的实用函数,可用于分组和执行多个协程或多个工作。

...
# run a collection of awaitables
results = await asyncio.gather(coro1(), asyncio.create_task(coro2()))

在咱们可能事后创立许多工作或协程而后心愿一次执行它们并期待它们全副实现后再持续的状况下,咱们能够应用 asyncio.gather() 函数。

这是一种可能的状况,其中须要许多相似工作的后果,例如具备不同数据的雷同工作或协程。

可期待对象能够并发执行,返回后果,并且主程序能够通过应用它所依赖的后果来复原。

gather() 函数比简略地期待工作实现更弱小。它容许将一组可期待对象视为单个可期待对象。

  • 通过 await 表达式执行并期待组中的所有可期待对象实现。
  • 从所有分组的期待对象中获取后果,稍后通过 result() 办法检索。
  • 要通过 cancel() 办法勾销的一组期待对象。
  • 通过 done() 办法检查组中的所有可期待对象是否已实现。
  • 仅当组中的所有工作实现时才执行回调函数。

2. 如何应用 Asyncio gather()

在本节中,咱们将认真钻研如何应用 asyncio.gather() 函数。

asyncio.gather() 函数将一个或多个可期待对象作为参数。回忆一下,可期待对象可能是协程、Future 或 Task。

因而,咱们能够调用 gather() 函数:

  • 多项工作
  • 多个协程
  • 工作和协程的混合
...
# execute multiple coroutines
asyncio.gather(coro1(), coro2())

如果 Task 对象被提供给 gather(),它们将曾经在运行,因为 Tasks 被安顿为创立的一部分。asyncio.gather() 函数将可期待对象作为地位参数。

咱们不能创立可期待对象的列表或汇合并将其提供给收集,因为这会导致谬误。

...
# cannot provide a list of awaitables directly
asyncio.gather([coro1(), coro2()])

如果首先应用星号运算符 (*) 将其解压缩到独自的表达式中,则能够提供期待列表。

...
# gather with an unpacked list of awaitables
asyncio.gather(*[coro1(), coro2()])

如果协程提供给 gather(),它们会主动包装在 Task 对象中。gather() 函数不会阻塞。

相同,它返回一个代表可期待对象组的 asyncio.Future 对象。

...
# get a future that represents multiple awaitables
group = asyncio.gather(coro1(), coro2())

一旦创立了 Future 对象,它就会在事件循环中主动调度。awaitable 代表组,组中的所有 awaitable 都会尽快执行。这意味着如果调用者什么都不做,那么预约的可期待对象组将运行(假如调用者挂起)。

这也意味着您不用期待从 gather() 返回的 Future。

...
# get a future that represents multiple awaitables
group = asyncio.gather(coro1(), coro2())
# suspend and wait a while, the group may be executing..
await asyncio.sleep(10)

能够期待返回的 Future 对象,它将期待组中的所有可期待对象实现。

...
# run the group of awaitables
await group

期待从 gather() 返回的 Future 将返回可期待对象的返回值列表。

如果可期待对象没有返回值,则此列表将蕴含默认的“无”返回值。

...
# run the group of awaitables and get return values
results = await group

这通常在一行中执行。

...
# run tasks and get results on one line
results = await asyncio.gather(coro1(), coro2())

3. 列表中多个协程的 gather() 示例

事后创立多个协程而后再收集它们是很常见的。这容许程序筹备要并发执行的工作,而后立刻触发它们的并发执行并期待它们实现。

咱们能够手动或应用列表了解将许多协程收集到一个列表中。

...
# create many coroutines
coros = [task_coro(i) for i in range(10)]

而后咱们能够用列表中的所有协程调用 gather()。协程列表不能间接提供给 gather() 函数,因为这会导致谬误。相同,gather() 函数要求将每个可期待对象作为独自的地位参数提供。

这能够通过将列表开展为独自的表达式并将它们传递给 gather() 函数来实现。星号运算符 (*) 将为咱们执行此操作。

...
# run the tasks
await asyncio.gather(*coros)

将它们联合在一起,上面列出了应用 gather() 运行事后筹备好的协程列表的残缺示例。

# SuperFastPython.com
# example of gather for many coroutines in a list
import asyncio
 
# coroutine used for a task
async def task_coro(value):
    # report a message
    print(f'>task {value} executing')
    # sleep for a moment
    await asyncio.sleep(1)
 
# coroutine used for the entry point
async def main():
    # report a message
    print('main starting')
    # create many coroutines
    coros = [task_coro(i) for i in range(10)]
    # run the tasks
    await asyncio.gather(*coros)
    # report a message
    print('main done')
 
# start the asyncio program
asyncio.run(main())

运行该示例会执行 main() 协程作为程序的入口点。main() 协程而后应用列表了解创立一个蕴含 10 个协程对象的列表。而后将此列表提供给 gather() 函数,并应用星号运算符将其解压缩为 10 个独自的表达式。

而后 main() 协程期待从调用 gather() 返回的 Future 对象,暂停并期待所有调度的协程实现它们的执行。协程会尽快运行,报告它们独特的音讯并在终止前休眠。

只有在组中的所有协程都实现后,main() 协程才会复原并报告其最终音讯。这突出了咱们如何筹备协程汇合并将它们作为独自的表达式提供给 gather() 函数。

main starting
>task 0 executing
>task 1 executing
>task 2 executing
>task 3 executing
>task 4 executing
>task 5 executing
>task 6 executing
>task 7 executing
>task 8 executing
>task 9 executing
main done

本文由 mdnice 多平台公布

退出移动版