使异步收集等待所有任务完成

问题描述 投票:1回答:1

我应该并行运行并收集数据一秒钟,然后在经过一段时间后返回数据。

问题是,据我所知,一个任务在另一任务之前完成,导致results在该结果上为空。例如下面的代码:

import asyncio
import time

async def task(id, end_time):
    print('Started task ', id)
    results = []
    while time.time() < end_time:
        results.append(1)
    return results


async def main():
    while True:
        end_time = time.time() + 1
        results = await asyncio.gather(*[task(i,end_time) for i in range(2)])
        print(len(results[0]), len(results[1]))
try:
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
except KeyboardInterrupt:
    pass
finally:
    loop.close()

返回

Started task  0
Started task  1
5580452 0

我要去哪里错了?我知道我应该以某种方式使其等待所有任务完成,然后再处理结果,但是经过一段时间摆弄不同的事情之后,我真的不知道如何实现这一目标。

python asyncio
1个回答
1
投票

您无需gather使用不同的名称。您可以使用asyncio的方式。

task协程中,删除while并仅附加到results一次。您将看到两个任务都将返回其输出。

问题是,当您执行while time.time()时,您将其锁定,因为它不是异步的。因此它将运行while循环,直到满足end_time条件为止。

然后第二个开始,因为task coro从未允许其间执行任何其他操作。因为两个都使用相同的end_time,所以第二个coro将永远不会追加。

如果要异步运行while循环,则需要为其创建附加的异步逻辑,并需要在await函数中创建它的task

编辑:例如,如果您只想将其放回事件循环并允许执行其他操作,只需将await asyncio.sleep(0.1)放入while循环中即可。

示例:

async def task(id, end_time):
    print('Started task ', id)
    results = []
    while time.time() < end_time:
        results.append(1)
        await asyncio.sleep(000000000.1)
    return results

改进空间:-asyncio.run(main()负责创建事件循环-追加到列表是一项昂贵的操作,请循环尝试+= 1,这样您的results将以0开头,然后打印结果,而不是其len

© www.soinside.com 2019 - 2024. All rights reserved.