关山难越,谁悲失路之人;萍水相逢,尽是他乡之客。
百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程教程 > 技术文章 > 正文

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

guanshanw 2023-09-26 12:23 23 浏览 0 评论

asyncio 的一个好处是我们可以同时运行许多协程。这些协同程序可以在一个组中创建并存储,然后同时一起执行。这可以使用 asyncio.gather() 函数来实现。

让我们仔细看看。

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

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

动动发财的小手,点个赞吧!

相关推荐

七条简单命令让您玩转Git
七条简单命令让您玩转Git

凭借着出色的协作能力、快速部署效果与代码构建辅助作用,Git已经得到越来越多企业用户的青睐。除了用于开发商业及消费级应用之外,众多科学及政府机构也开始尝试使用这...

2023-10-07 12:14 guanshanw

基本完整的关于Git分支branch的操作
基本完整的关于Git分支branch的操作

Git使用背景项目中要用到dev或者其他分支开发完代码,需要将该分支合并到master的需求操作步骤下面以dev名称为lex为分支名为例来操作一遍客户端操作:...

2023-10-07 12:14 guanshanw

Git 进阶(合并与变基)
Git 进阶(合并与变基)

在Git中整合来自不同分支的修改主要有两种方法:合并(merge)以及变基(rebase)合并(merge)merge流程图merge的原理是找到这两个分...

2023-10-07 12:13 guanshanw

Git学习笔记 003 Git进阶功能 part5 合并(第一部分)

合并(merge)是很常用的操作。尤其是一个庞大的很多人参与开发的企业级应用。一般会设定一个主分支,和多个副分支。在副分支开发完成后,合并到主分支中。始终保持主分支是一个完整的,稳定的最新状态的分支。...

非标题党,三张图帮你理解git merge和git rebase的区别
非标题党,三张图帮你理解git merge和git rebase的区别

初始场景:基于正常的开发分支修改几个小bug,然后在合并到开发分支上。gitmergegitcheckoutfeaturegitmergeho...

2023-10-07 12:13 guanshanw

git 初次使用(01)
git 初次使用(01)

先从github上克隆代码下来:使用vscode克隆代码如下图,填写上github仓库地址:vscode有时候克隆代码速度比较慢,可以用命令行方式克隆gitc...

2023-10-07 12:12 guanshanw

Git 远程操作

4.Git远程操作命令说明gitremote远程版本库操作gitfetch从远程获取版本库gitpull下载远程代码并合并gitpush上传远程代码并合并4.1远程版本库操作gitre...

Git常用命令-总结
Git常用命令-总结

创建git用户$gitconfig--globaluser.name"YourName"$gitconfig--globaluser.em...

2023-10-07 12:12 guanshanw

git中删除从别人clone下来项目的git信息,并修改为自己的分支

如果你从别人的Git存储库中克隆了一个项目,并想要删除与该存储库相关的Git信息,并将其修改为你自己的分支,则可以执行以下步骤:使用gitclone命令克隆存储库:gitclone<u...

git系列-回滚和放弃本地修改

回滚历史提交就是reset的功能。这种情况是已经提交远程仓库,需要回滚到之前的提交。gitreset--hardcommitId//注:强制提交后,当前版本后面的提交版本将会删掉!gi...

GIT使用小技巧大全
GIT使用小技巧大全

在大型软件工程的开发过程中,版本控制是无法绕过去的;目前来说,最火的版本控制软件就是GIT了。早两年SVN比较火,不过被大神linus喷了几次后,就日落西山了,...

2023-10-07 12:11 guanshanw

git相关命令-上
git相关命令-上

这些命令都是看了文档后,个人觉得比较有用的一些,展示给大家。回到远程仓库的状态抛弃本地所有的修改,回到远程仓库的状态。gitfetch--all&...

2023-10-07 12:10 guanshanw

Git命令行接口:掌握Git的必备技能
Git命令行接口:掌握Git的必备技能

Git是一款强大的分布式版本控制工具,它支持命令行界面操作。熟练掌握Git命令行接口,是开发者使用Git的必备技能之一。在这篇文章中,我们将介绍Git命令行接口...

2023-10-07 12:10 guanshanw

Git命令详解
Git命令详解

相信各位小伙伴们应该都对git有一些了解,毕竟作为代码管理的神器,就算不是IT行业的小伙伴肯定也或多或少的听说过一些。今天就来和小伙伴们分享一下自己总结的常用命...

2023-10-07 12:10 guanshanw

工作7年收集到的git命令
工作7年收集到的git命令

概念git中的术语解释:仓库也叫版本库(repository)stage:暂存区,add后会存到暂存区,commit后提交到版本库git安装linux...

2023-10-07 12:10 guanshanw

取消回复欢迎 发表评论: