Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - Cancel timer thread

Tags:

python

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?

like image 892
Hanpan Avatar asked Nov 28 '22 18:11

Hanpan


2 Answers

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.

like image 199
senderle Avatar answered Dec 06 '22 19:12

senderle


You just need to set the Timer thread as a daemon

def hello_world(self):
    print 'Hello!'
    t = threading.Timer(2,hello_world)
    t.daemon = True
    t.start()

That will cause it to exit when the main thread exits, e.g. due to KeyboardInterrupt.

The daemon setting causes the entire program to exit when the only threads left are daemon threads.

like image 34
Chris Redford Avatar answered Dec 06 '22 19:12

Chris Redford