如何使用Ctrl-C优雅地终止asyncio脚本? [英] How to gracefully terminate an asyncio script with Ctrl-C?

查看:415
本文介绍了如何使用Ctrl-C优雅地终止asyncio脚本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了所有我能找到的有关如何用asyncio事件循环以Ctrl-C终止的脚本来优雅地处理脚本的文章,而且我一直无法在不打印一个或多个脚本的情况下使它们中的任何一个正常工作回溯,因为我这样做.答案几乎无处不在,我还无法在这个小脚本中实现其中的任何一个:

I've read every post I could find about how to gracefully handle a script with an asyncio event loop getting terminated with Ctrl-C, and I haven't been able to get any of them to work without printing one or more tracebacks as I do so. The answers are pretty much all over the place, and I haven't been able implement any of them into this small script:

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.在我根据先前的答案尝试过的许多其他形式中,我得到了许多其他类型的异常类和错误消息,但不知道如何解决它们.上面的代码现在很少,但是我之前所做的一些尝试不过是什么,而且都不是正确的.

What I want to happen is for the script to exit without printing any tracebacks following a Ctrl-C (or SIGTERM/SIGINT sent via kill). This code prints RuntimeError: Event loop stopped before Future completed. In the MANY other forms I've tried based on previous answers, I've gotten a plethora of other types of exception classes and error messages with no idea how to fix them. The code above is minimal right now, but some of the attempts I made earlier were anything but, and none of them were correct.

如果您能够修改脚本以使其优雅地终止,那么不胜感激地解释为什么您的操作方式是 right 方法.

If you're able to modify the script so that it terminates gracefully, an explanation of why your way of doing it is the right way would be greatly appreciated.

推荐答案

在事件循环运行时停止该事件循环将永远无效.

Stopping the event loop while it is running will never be valid.

在这里,您需要捕获Ctrl-C来向Python表示您希望自己处理它,而不是显示默认的堆栈跟踪.这可以通过经典的try/except来完成:

Here, you need to catch the Ctrl-C, to indicate to Python that you wish to handle it yourself instead of displaying the default stacktrace. This can be done with a classic try/except:

coro = display_date(loop)
try:
    loop.run_until_complete(coro)
except KeyboardInterrupt:
    print("Received exit, exiting")

就您的用例而言,就是这样! 对于更真实的程序,您可能需要清理一些资源.另请参见平稳关闭asyncio协程

And, for your use-case, that's it! For a more real-life program, you would probably need to cleanup some resources. See also Graceful shutdown of asyncio coroutines

这篇关于如何使用Ctrl-C优雅地终止asyncio脚本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆