首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用asyncio编写的程序运行时间与同步版本相同

使用asyncio编写的程序运行时间与同步版本相同
EN

Stack Overflow用户
提问于 2019-12-29 17:56:45
回答 1查看 104关注 0票数 0

我开始学习python asyncio模块。我正在写一个基本的程序,它基本上是等待一段时间,然后打印结果。

代码语言:javascript
复制
async def say_helloworld(wait:int)->None:
    print(f"starting say_helloworld({wait})")
    await asyncio.sleep(wait)
    print(f"say_helloworld({wait}) says hello world!")

我编写了上面给出的协程,并创建了一些任务。

代码语言:javascript
复制
tasks = (asyncio.create_task(say_helloworld(i)) for i in range(10))

然后,我将任务包装在另一个协程中。

代码语言:javascript
复制
async def main(tasks):
    for task in tasks:
        await task

最后,我运行了包装器协程

代码语言:javascript
复制
asyncio.run(main(tasks))

我的预期是程序将在大约10秒内完成,因为每个任务将同时等待,而不是以同步的方式。但是,程序几乎花了45秒(同步?)。我遗漏了什么?为什么它像同步程序一样运行?

EN

回答 1

Stack Overflow用户

发布于 2019-12-29 21:25:56

我按照上面给出的方式编写了协程,并创建了一些任务。

问题是你的代码,正如所写的,实际上并不是提前创建任务,它只是提供了一个在需要的时候如何创建任务的方法。tasks被初始化为:

代码语言:javascript
复制
tasks = (asyncio.create_task(say_helloworld(i)) for i in range(10))

上面是一个生成器表达式,它只会在您迭代时创建任务。因此,虽然目的是提前创建任务,然后在它们并行运行时等待它们,但实际实现在每次迭代中创建单个任务,然后立即等待它。这会导致按顺序执行任务的不良结果。

修复方法是通过从(asyncio.create_task... )切换到[asyncio.create_task... ]来构建一个实际的列表。您还需要在协程中执行此操作,以便为任务运行一个事件循环。例如:

代码语言:javascript
复制
# ... say_helloworld defined as before ...

async def main():
    tasks = [asyncio.create_task(say_helloworld(i)) for i in range(10)]
    for task in tasks:
        await task

asyncio.run(main())

这导致了十个“开始...”消息之后只有一次停顿和十次“表示你好...”消息,这是最初的目标。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59518372

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档