I'm currently repeating a task in a for loop inside a callback using Twisted, but would like the reactor to break the loop in the callback (one) if the user issues a KeyboardInterrupt via Ctrl-C. From what I have tested, the reactor only stops or processes interrupts at the end of the callback.
Is there any way of sending a KeyboardInterrupt to the callback or the error handler in the middle of the callback run?
Cheers,
Chris
#!/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()
I got this working dandy. The fired SIGINT sets a flag running for any running task in my code, and additionally calls reactor.callFromThread(reactor.stop) to stop any twisted running code:
#!/usr/bin/env python
import sys
import twisted
import re
from twisted.internet import reactor, defer, task
import signal
def one(result, token):
print "Start one()"
for i in xrange(1000):
print i
if token.running is False:
raise KeyboardInterrupt()
#reactor.callFromThread(reactor.stop) # this doesn't work
print "End one()"
def oneErrorHandler(failure):
print "INTERRUPTING one(): Unkown Exception"
import traceback
print traceback.format_exc()
reactor.stop()
def oneKeyboardInterruptHandler(failure):
failure.trap(KeyboardInterrupt)
print "INTERRUPTING one(): KeyboardInterrupt"
reactor.stop()
def repeatingTask(token):
d = defer.Deferred()
d.addCallback(one, token)
d.addErrback(oneKeyboardInterruptHandler)
d.addErrback(oneErrorHandler)
d.callback('result')
class Token(object):
def __init__(self):
self.running = True
def sayBye():
print "bye bye."
if __name__ == '__main__':
token = Token()
def customHandler(signum, stackframe):
print "Got signal: %s" % signum
token.running = False # to stop my code
reactor.callFromThread(reactor.stop) # to stop twisted code when in the reactor loop
signal.signal(signal.SIGINT, customHandler)
t2 = task.LoopingCall(reactor.callLater, 0, repeatingTask, token)
t2.start(5)
reactor.addSystemEventTrigger('during', 'shutdown', sayBye)
print "STARTING REACTOR..."
reactor.run()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With