2

I have a function I'm calling every 5 seconds like such:

def check_buzz(super_buzz_words):
    print 'Checking buzz'
    t = Timer(5.0, check_buzz, args=(super_buzz_words,))
    t.dameon = True
    t.start()
    buzz_word = get_buzz_word()
    if buzz_word is not 'fail':
        super_buzz_words.put(buzz_word)

main()
 check_buzz()

I'm exiting the script by either catching a KeyboardInterrupt or by catching a System exit and calling this:

sys.exit('\nShutting Down\n')

I'm also restarting the program every so often by calling:

execv(sys.executable, [sys.executable] + sys.argv)

My question is, how do I get that timer thread to shut off? If I keyboard interrupt, the timer keeps going.

6
  • 1
    Where are you able to catch the KeyboardInterrupt? Can you call t.cancel() when you catch it? Could you set a flag to check to see if you should exit rather than invoking another timer instance? Commented Apr 16, 2015 at 0:21
  • Perhaps make a function with atexit that calls t.cancel()? Commented Apr 16, 2015 at 0:23
  • sys.exit() takes an integer error code. And you can call t.cancel(). Commented Apr 16, 2015 at 0:24
  • I'm not too familiar with Timer obj, but considering the thread is a dameon wouldn't it shut down with the rest of the script? Commented Apr 16, 2015 at 0:27
  • You say the timer (and thus the script) keeps executing when you call sys.exit? sys.exit just raises SystemExit so if you are also catching SystemExit you may have a problem with that handler. The script and the timer should be gone when you call exit. Commented Apr 16, 2015 at 0:48

4 Answers 4

3

I think you just spelled daemon wrong, it should have been:

t.daemon = True

Then sys.exit() should work

Sign up to request clarification or add additional context in comments.

Comments

1

Expanding on the answer from notorious.no, and the comment asking:

How can I call t.cancel() if I have no access to t oustide the function?

Give the Timer thread a distinct name when you first create it:

import threading

def check_buzz(super_buzz_words):
    print 'Checking buzz'
    t = Timer(5.0, check_buzz, args=(super_buzz_words,))
    t.daemon = True
    t.name = "check_buzz_daemon"
    t.start()

Although the local variable t soon goes out of scope, the Timer thread that t pointed to still exists and still retains the name assigned to it.

Your atexit-registered method can then identify this thread by its name and cancel it:

from atexit import register

def all_done():
    for thr in threading._enumerate():
        if thr.name == "check_buzz_daemon":
            if thr.is_alive():
                thr.cancel()
                thr.join()

register(all_done)

Calling join() after calling cancel()is based on a StackOverflow answer by Cédric Julien.

HOWEVER, your thread is set to be a Daemon. According to this StackOverflow post, daemon threads do not need to be explicitly terminated.

Comments

0
from atexit import register

def all_done():
    if t.is_alive():
        # do something that will close your thread gracefully

register(all_done)

Basically when your code is about to exit, it will fire one last function and this is where you will check if your thread is still running. If it is, do something that will either cancel the transaction or otherwise exit gracefully. In general, it's best to let threads finish by themselves, but if it's not doing anything important (please note the emphasis) than you can just do t.cancel(). Design your code so that threads will finish on their own if possible.

2 Comments

How can I call t.cancel() if I have no access to t oustide the function? It seems like based on Python's Timer class you have to set this up recursively and therefore can't access the timer object?
Then create a reference to it outside the function. One thing that comes to mind would be for check_buzz() to return t this way you can store it in a global variable and/or pass is to other functions.
0

Another way would be to use the Queue() module to send and recieve info from a thread using the .put() outside the thread and the .get() inside the thread. What you can also do is create a txt file and make program write to it when you exit And put an if statement in the thread function to check it after each iteration (this is not a really good solution but it also works) I would have put a code exemple but i am writing from mobile sorry

Comments