使用create_task()或collect()效率更高吗?

hed*_*wig 2 python-3.x python-asyncio

我仍然使用异步python的基础知识,有些事情使我感到困惑。

import asyncio
loop=asyncio.get_event_loop()
for variation in args:
    loop.create_task(coroutine(variation))
loop.run_forever()
Run Code Online (Sandbox Code Playgroud)

似乎与此非常相似

import asyncio
loop=asyncio.get_event_loop()
loop.run_forever(
    asyncio.gather(
        coroutine(variation_1),
        coroutine(variation_2),
        ...))
Run Code Online (Sandbox Code Playgroud)

他们可能会做同样的事情,但这似乎没有用,所以有什么区别?

use*_*342 6

如评论中所述,您的第二个示例应使用run_until_complete,而不是run_forever

他们可能会做同样的事情,但这似乎没有用,所以有什么区别?

asyncio.gather 是更高层次的构造。

  • create_task将协程提交到事件循环,以有效地使其在“后台”运行(前提是事件循环本身处于活动状态)。顾名思义,它会返回一个task,一个执行协程的句柄,最重要的是提供了取消它的能力。您可以在事件循环中创建任意数量的此类任务,它们将一直运行到各自完成为止。

  • asyncio.gather用于当您实际对生成的协程的结果感兴趣时。它像一样使用生成它们create_task,允许它们并行运行,但也等待它们全部完成,然后返回它们各自的结果(或者如果它们中的任何一个引发了异常,则引发异常)。

例如,如果您有一个download协程可以下载URL并返回其内容,并且您正在下载URL列表,则gather可以将URL与其数据进行匹配:

url_list = [...]
data_list = await asyncio.gather(*[download(url) for url in url_list]

# url_list and data_list now have matching elements, so this works:
for url, data in zip(url_list, data_list):
    ...
Run Code Online (Sandbox Code Playgroud)

用just做到这一create_task点将更加复杂。