Reputation: 1370
I've got a simple program with a function that's scheduled to run every 10 seconds using threading.Timer()
. However I can't easily kill it with Ctrl+C - it keeps resisting and I have to ^C it multiple times to kill it. Here is my sample code that exhibits this behaviour:
#!/usr/bin/env python
import sys
import time
from threading import Timer
def scheduled_function():
Timer(10, scheduled_function).start()
print("Scheduled function called...\n")
if __name__ == "__main__":
scheduled_function()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
sys.exit(0)
And here is what happens when I run it and Ctrl+C it:
$ python timer.py
Scheduled function called...
^C^C^C^C^CScheduled function called...
Exception KeyboardInterrupt in <module 'threading' from '/usr/lib/python2.7/threading.pyc'> ignored
Unhandled exception in thread started by
sys.excepthook is missing
lost sys.stderr
Note how many times I had to use ^C to kill it. I guess it was waiting for the timer to expire and only then exitted.
Is there a clean way to catch KeyboardInterrupt and kill all the threads immediately?
Upvotes: 2
Views: 1713
Reputation: 133879
The first Ctrl-C did probably get to the exception handler. However, sys.exit(0)
waits for all non-daemonic threads to exit. Timer
is a subclass of thread, but it is not daemonic by default.
The solution is to make it a daemon, unfortunately it doesn't look as clean now
def scheduled_function():
t = Timer(10, scheduled_function)
t.daemon = True
t.start()
With this change:
Scheduled function called...
^C
%
Upvotes: 4