python gevent:KeyboardInterrupt 中的意外输出

python gevent: unexpected output in KeyboardInterrupt

运行 这个代码

import gevent

def f():
    while True:
        gevent.sleep(1)

if __name__ == '__main__':
    tasks = (gevent.spawn(f),)
    try:
        gevent.wait(tasks)
    except KeyboardInterrupt:
        print("KeyboardInterrupt trapped")

然后按 Ctrl-C,给我这个输出:

$ python receiver.py 
^CKeyboardInterrupt
Tue Aug  8 00:56:04 2017
KeyboardInterrupt trapped

为什么?
好像有人在输出上写退出时间。
如何防止第一行出现 KeyboardInterrupt 而第二行出现日期?

这些消息由 gevent Hub 打印,它正在拦截正在引发的 KeyboardInterrupt。通常你会看到回溯,而不仅仅是 KeyboardInterrupt 和当前日期,但因为集线器很特殊,你会得到那个输出。

您有两种方法可以解决这个问题:

  1. 将 KeyboardInterrupt 标记为非错误:

    gevent.get_hub().NOT_ERROR += (KeyboardInterrupt,)
    

    通过这个技巧,Hub 在捕获到 KeyboardInterrupt 时不会打印任何行。这似乎是一个 hack,但它是停止输出污染的一种简短而有效的方法。

  2. 为 SIGINT 注册一个信号处理程序:

    def handler(signum, frame):
        print('SIGINT trapped')
        sys.exit(0)
    
    signal.signal(signal.SIGINT, handler)
    

    SIGINT 的默认信号处理程序将引发 KeyboardInterrupt,但如果您定义自己的信号处理程序,则可以阻止它并 运行 您的清理代码。

    重要的是您在处理函数中出现异常退出,否则您对 gevent.wait() 的调用将不会停止。您可以使用的唯一两个异常是 SystemExit 和 GreenletExit(这是上面 NOT_ERROR 列表中的两个默认异常):任何其他异常都会导致 gevent 在标准错误上打印一些东西。