Python - Cancel timer thread
Question: I'm trying to create a method which runs on a timer in the background of my
main script:

    
    
    def hello_world(self):
            print 'Hello!'
            threading.Timer(2,hello_world).start()
    
    if __name__ == "__main__":
        try:
            hello_world()
        except KeyboardInterrupt:
            print '\nGoodbye!'
    

I am getting this message when I attempt to keyboard interrupt my script:

    
    
    Exception KeyboardInterrupt in <module 'threading' from '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/threading.py'> ignored
    

How do I close the thread so that I can exit my application cleanly?


Answer: To elaborate a bit on Aphex's answer, the main thread can't possibly catch the
KeyboardInterrupt signal, unless you have very fast fingers. The main thread
exits almost immediately! Try this:

    
    
    import threading
    
    def hello_world():
            print 'Hello!'
            threading.Timer(2,hello_world).start()
    
    if __name__ == "__main__":
        try:
            hello_world()
        except KeyboardInterrupt:
            print '\nGoodbye!'
        print "main thread exited"
    

More generally, I would not suggest using a self-calling timer like this, just
because it creates a lot of threads. Just create one thread and call
`time.sleep` inside it.

However, as long as you keep the main thread running, you seem to be able to
catch `KeyboardInterrupt` inside. The trick then is to make the thread a
`daemon` thread that exits when the main thread exits.

    
    
    import threading
    import time
    
    def hello_world():
        while(True):
            print 'Hello!'
            time.sleep(2)
    
    if __name__ == "__main__":
        hw_thread = threading.Thread(target = hello_world)
        hw_thread.daemon = True
        hw_thread.start()
        try:
            time.sleep(1000)
        except KeyboardInterrupt:
            print '\nGoodbye!'
    

This exits automatically after 1000 seconds -- you could make that number even
bigger if you like. You could also use a busy-loop to repeat the sleep call,
but I don't really see the point.

