我应该并行运行一些函数并收集数据一秒钟,然后在经过一段时间后返回数据。
问题是,(据我所知)一项任务在另一项之前完成,导致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
我要去哪里错了?我知道我应该以某种方式使其等待所有任务完成,然后再处理结果,但是经过一段时间摆弄不同的事情之后,我真的不知道如何实现这一目标。
答案 0 :(得分:2)
您不需要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