我目前正在使用Twisted在回调内的for循环中重复执行任务,但如果用户通过Ctrl-C发出KeyboardInterrupt,希望反应堆中断回调(一个)中的循环。根据我的测试,反应堆仅在回调结束时停止或处理中断。

有什么方法可以将KeyboardInterrupt发送到回调或回调运行中间的错误处理程序?

干杯,

克里斯

#!/usr/bin/env python

from twisted.internet import reactor, defer


def one(result):
    print "Start one()"
    for i in xrange(10000):
        print i
    print "End one()"
    reactor.stop()


def oneErrorHandler(failure):
    print failure
    print "INTERRUPTING one()"
    reactor.stop()


if __name__ == '__main__':

    d = defer.Deferred()
    d.addCallback(one)
    d.addErrback(oneErrorHandler)
    reactor.callLater(1, d.callback, 'result')

    print "STARTING REACTOR..."
    try:
        reactor.run()
    except KeyboardInterrupt:
        print "Interrupted by keyboard. Exiting."
        reactor.stop()

最佳答案

这是为了避免(半)抢占,因为Twisted是协作式多任务处理系统。 Ctrl-C在Python中使用解释器在启动时安装的SIGINT处理程序进行处理。处理程序在调用时设置一个标志。在执行每个字节代码之后,解释器将检查标志。如果已设置,则此时会引发KeyboardInterrupt。

反应器安装自己的SIGINT处理程序。这代替了解释程序处理程序的行为。反应堆的处理程序启动反应堆关闭。由于它不会引发异常,因此它不会中断正在运行的任何代码。循环(或其他任何循环)完成,当控制权返回到反应堆时,关闭继续进行。

如果您想让Ctrl-C(即SIGINT)提高KeyboardInterrupt,那么您可以使用信号模块来还原Python的SIGINT处理程序:

signal.signal(signal.SIGINT, signal.default_int_handler)


但是请注意,如果在运行Twisted中的代码而不是您自己的应用程序代码时发送SIGINT,则该行为是不确定的,因为Twisted不会被KeyboardInterrupt中断。

08-25 14:58