首页 > 编程语言 >Python 异步: 同时运行多个协程(10)

Python 异步: 同时运行多个协程(10)

时间:2023-02-19 22:35:49浏览次数:57  
标签:10 task 协程 Python gather 对象 等待 asyncio

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多平台发布

标签:10,task,协程,Python,gather,对象,等待,asyncio
From: https://www.cnblogs.com/swindler/p/17135809.html

相关文章

  • 10.MyBatis-Plus的使用
    整合MyBatis-Plus导入依赖在解决逆向工程生成的代码报错时候已经给bianen-common导入了依赖导入数据库的驱动导入驱动和MySql的版本有关,我安装的MySql版本是5.7.36打......
  • 用Lock和Condition,实现主线程执行5次,子线程再执行10次,孙线程执行15次,如此反复5次
    packagetest1;importjava.util.concurrent.locks.Condition;importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;/***用Lock和C......
  • Python selenium
    目录selenium功能Python实现seleniumSelenium是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7,8,9,......
  • 103、商城业务---消息队列---RabbitTemplate的使用
    使用RabbitTemplate可以发送消息使用RabbitTemplate发送消息,如果消息是一个字符串则直接发送。如果是对象,则默认是使用序列化机制发送出去我们也可以使用json格式发送,......
  • 10年磨一剑,.net 公共类库,终于初版
    1、vs搜索nuget MathSoftCommonLib漫思公司前端工具库MathSoftModelLib  漫思公司前端基础模型库2、目前已经全部开源,在github上jidanji/MathSoftCommonLib(githu......
  • window10修改mstsc3389端口
    概述完成修改window10/11默认3389端口为其他端口01、regeditwin+r//输入regedit打开注册表regedit02、修改PortNumber3389->x##m1注册表形式//改为自定......
  • python中的类继承
    """"""classAnimal(object):def__init__(self,name,food):self.name=nameself.food=foodself.blood=100self.waise......
  • 向日葵RCE复现CNVD-2022-10270/CNVD-2022-03672
    前言向日葵是一款免费的集远程控制电脑手机、远程桌面连接、远程开机、远程管理、支持内网穿透的一体化远程控制管理工具软件。于2022年2月5日和2022年2月15日,CNVD公开上海......
  • day10
    变量变量就是可变化的量Java是强类型语言,每个变量必须声明其类型Java变量是程序中最基本的存储单位(变量名,变量类型和作用域)注意:每个变量都有类型,类型可以是基本类型,......
  • FPGA基于ACM2108的DDS设计
    这次设计一个DDS信号发生器。该设计的特点有:双通道的DA输出,可以调节频率、相位、和波形(正弦波、方波、三角波)。拥有相位重置的功能,能够同时重置两个输出波形的相位。本......