异步、等待和无限循环
Posted
技术标签:
【中文标题】异步、等待和无限循环【英文标题】:Asyncio, await and infinite loops 【发布时间】:2017-12-12 10:25:01 【问题描述】:async def start(channel):
while True:
m = await client.send_message(channel, "Generating... ")
generator.makeFile()
with open('tmp.png', 'rb') as f:
await client.send_file(channel, f)
await client.delete_message(m)
await asyncio.sleep(2)
我有一个每 2 秒运行一次任务的不和谐机器人。我尝试为此使用无限循环,但脚本因Task was destroyed but it is still pending!
而崩溃我已经阅读了有关异步协程的信息,但我发现的示例中没有一个使用await
。例如,是否可以通过使用await
运行协程来避免此错误?
【问题讨论】:
await
在这里不是问题。更多while True
也是定期调用的常用方式(***.com/questions/37512182/…)。显示你是如何执行那个函数的,你是否试图在代码中停止这个任务?
【参考方案1】:
Task was destroyed but it is still pending!
是当您调用loop.close()
时收到的警告,当您的脚本中的某些tasks 未完成时。通常你应该避免这种情况,因为未完成的任务可能不会释放一些资源。您需要在事件循环关闭之前等待任务完成或cancel。
由于您有无限循环,您可能需要取消任务,例如:
import asyncio
from contextlib import suppress
async def start():
# your infinite loop here, for example:
while True:
print('echo')
await asyncio.sleep(1)
async def main():
task = asyncio.Task(start())
# let script some thime to work:
await asyncio.sleep(3)
# cancel task to avoid warning:
task.cancel()
with suppress(asyncio.CancelledError):
await task # await for task cancellation
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
loop.run_until_complete(main())
finally:
loop.run_until_complete(loop.shutdown_asyncgens())
loop.close()
有关任务的更多信息,另请参阅this answer。
【讨论】:
That answer 完美解决了,谢谢。此示例运行良好,但似乎要求无限循环将在某一点或另一点停止。 如果我在 main func 中以相同的顺序等待两个异步任务(task1 和 task2),则 task1 有一个 while true 循环,并在该 while 循环内再调用一个异步任务(task3)。在这种情况下,执行是否会传递给 task2? @y_159 抱歉,我很难跟上。你有机会用代码写这个吗? @MikhailGerasimov 谢谢,我通过脚本进行了测试,即使任务包含 while True 循环,异步也可以正常工作。以上是关于异步、等待和无限循环的主要内容,如果未能解决你的问题,请参考以下文章