我阅读了所有关于如何优雅地处理带有asyncio事件循环的脚本在使用Ctrl-C被终止的文章,但我无法使它们在不打印一个或多个tracebacks的情况下正常工作。答案几乎都是五花八门的,我也没能将它们中的任何一种实现到这个小脚本中:
import asyncio
import datetime
import functools
import signal
async def display_date(loop):
end_time = loop.time() + 5.0
while True:
print(datetime.datetime.now())
if (loop.time() + 1.0) >= end_time:
break
await asyncio.sleep(1)
def stopper(signame, loop):
print("Got %s, stopping..." % signame)
loop.stop()
loop = asyncio.get_event_loop()
for signame in ('SIGINT', 'SIGTERM'):
loop.add_signal_handler(getattr(signal, signame), functools.partial(stopper, signame, loop))
loop.run_until_complete(display_date(loop))
loop.close()
我希望脚本在按下Ctrl-C (或通过kill
发送的SIGTERM/SIGINT)后退出而不打印任何回溯。此代码会打印出RuntimeError: Event loop stopped before Future completed.
。我尝试了许多其他形式,基于以前的答案,但是得到了各种其他类型的异常类和错误消息,不知道如何修复它们。现在上面的代码很简短,但我之前尝试的一些方法则完全不同,而且都不正确。如果您能修改脚本使其优雅地终止,那么解释为什么您的方式是正确的将不胜感激。
asyncio.get_running_loop()
和asyncio.current_task()
分别获取循环和任务,这样我就可以在协程中添加信号处理程序(允许它使用asyncio.run()
调用)。 - Scott Stevens