如果一个任务完成,则完成异步收集的最佳方法



我有以下代码,其中function_1和function_2独立运行。但是,我希望脚本在完成后完成function_2。

import asyncio
from datetime import datetime
class class_example():
def __init__(self, bot):
asyncio.run(self.main())
async def main(self):
f1=asyncio.create_task(self.function_1())
f2=asyncio.create_task(self.function_2())
a = await asyncio.gather(f1, f2)

async def function_1(self):
await asyncio.sleep(0.1)
while True:
print(f'{(datetime.now().strftime("%F - %H:%M:%S:%f"))} - function_1')
await asyncio.sleep(1)
async def function_2(self):
i = 0
while True:
i += 1
print(f'{(datetime.now().strftime("%F - %H:%M:%S:%f"))} - function_2')
await asyncio.sleep(1)
if i == 10:
loop = asyncio.get_event_loop()
loop.close()
break
class manuel_run():
def __init__(self):
class_example(self)
if __name__ == '__main__':
a = manuel_run()

我收到此错误消息: 运行时错误: 无法关闭正在运行的事件循环

我添加了一个尝试/除了错误消息,它可以工作...但我相信应该有更好的方法来做到这一点吗?

try:
a = await asyncio.gather(f1, f2)
except RuntimeError as error:
print(error)
if 'Cannot close a running event loop' in str(error):
print("FINISHED")
else:
print(error)

在一般情况下,无条件关闭事件循环似乎是一个坏主意,因为您很可能有需要在程序结束之前运行的最终化任务。

简单而适当的出路是cancel另一项任务。您可以通过将f1作为实例上的属性来提供对的function_2访问权限来做到这一点;或(更好)在main中使用asyncio.wait(或as_completed或其他):

done, pending = await asyncio.wait([f1, f2], return_when=asyncio. FIRST_COMPLETED)
a = await (list(done)[0])
list(pending)[0].cancel()

请注意,您可能仍希望等待已取消的任务。

最新更新