Search code examples
pythonmultithreadingpython-2.7timer

Python timer start and reset


I am attempting to get a Timer functionality to work in Python (Python 2.7 currently).

Here is what I have so far. I am struggling with a threading issue and resetting the timer.

from threading import Timer

def api_call():
    print("Call that there api")

t = Timer(10.0,api_call)


def my_callback(channel):

    if something_true:
        print('reset timer and start again')
        t.cancel()
        t.start()
        print("\n timer started")
    elif something_else_true:
        t.cancel()
        print("timer canceled")
    else:
       t.cancel()
       print('cancel timer for sure')

try:
    if outside_input_that_can_happen_a_lot:
        my_callback()

finally:
    #cleanup objects

Basically, my_callback() can be called a lot of times very quickly and can hit any part of the "if", "elif", or "else" statements.

The issue I am having is that when the something_true variable is true, then it will start a timer. Which works great the first time. Every time after that that it is called, I get a threading error telling me that only one thread can be used for the timer.

Basically, I want to be able to reset my timer on the first "if" and cancel if the "elif" or "else" is hit.


Solution

  • Based on my testing, this is because threads can only be started once, and as the timer relies on a thread, the timer can only be started once. This means that the only way to re-start the timer would be to do:

    def newTimer():
        global t
        t = Timer(10.0,api_call)
    newTimer()
    

    instead of the t = Timer part, and do

    t.cancel()
    newTimer()
    t.start()
    

    instead of the current re-start code.

    This makes your full code:

    from threading import Timer
    
    def api_call():
        print("Call that there api")
    
    def newTimer():
        global t
        t = Timer(10.0,api_call)
    newTimer()
    
    
    def my_callback(channel):
    
        if something_true:
            print('reset timer and start again')
            t.cancel()
            newTimer()
            t.start()
            print("\n timer started")
        elif something_else_true:
            t.cancel()
            print("timer canceled")
        else:
           t.cancel()
           print('cancel timer for sure')
    
    try:
        if outside_input_that_can_happen_a_lot:
            my_callback()
    
    finally:
        #cleanup objects
    

    Hope this helps.