Calling thread.timer() more than once

后端 未结 2 1783
半阙折子戏
半阙折子戏 2021-01-14 20:49

The code:

from threading import Timer
import time

def hello():
    print \"hello\"

a=Timer(3,hello,())
a.start()
time.sleep(4)
a.start()

相关标签:
2条回答
  • 2021-01-14 21:19

    Since I'm used to start my oven timer each time I bake a cookie, I was surprised to see that python's timers are one-shot only. That said I share a small timer class which btw offers some more options on the start method:

    • returns itself to allow a one line timer creation and start
    • optional parameter to restart a new timer or not if timer is still alive

    Implementation:

    from threading import Timer, Lock
    
    
    class TimerEx(object):
        """
        A reusable thread safe timer implementation
        """
    
    def __init__(self, interval_sec, function, *args, **kwargs):
        """
        Create a timer object which can be restarted
    
        :param interval_sec: The timer interval in seconds
        :param function: The user function timer should call once elapsed
        :param args: The user function arguments array (optional)
        :param kwargs: The user function named arguments (optional)
        """
        self._interval_sec = interval_sec
        self._function = function
        self._args = args
        self._kwargs = kwargs
        # Locking is needed since the '_timer' object might be replaced in a different thread
        self._timer_lock = Lock()
        self._timer = None
    
    def start(self, restart_if_alive=True):
        """
        Starts the timer and returns this object [e.g. my_timer = TimerEx(10, my_func).start()]
    
        :param restart_if_alive: 'True' to start a new timer if current one is still alive
        :return: This timer object (i.e. self)
        """
        with self._timer_lock:
            # Current timer still running
            if self._timer is not None:
                if not restart_if_alive:
                    # Keep the current timer
                    return self
                # Cancel the current timer
                self._timer.cancel()
            # Create new timer
            self._timer = Timer(self._interval_sec, self.__internal_call)
            self._timer.start()
        # Return this object to allow single line timer start
        return self
    
    def cancel(self):
        """
        Cancels the current timer if alive
        """
        with self._timer_lock:
            if self._timer is not None:
                self._timer.cancel()
                self._timer = None
    
    def is_alive(self):
        """
        :return: True if current timer is alive (i.e not elapsed yet)
        """
        with self._timer_lock:
            if self._timer is not None:
                return self._timer.is_alive()
        return False
    
    def __internal_call(self):
        # Release timer object
        with self._timer_lock:
            self._timer = None
        # Call the user defined function
        self._function(*self._args, **self._kwargs)
    

    Here an example:

    from time import sleep
    
    def my_func(msg):
        print(msg)
    
    my_timer = TimerEx(interval_sec=5, function=my_func, msg="Here is my message").start()
    sleep(10)
    my_timer.start()
    sleep(10)
    

    Note: I'm using python 3.7, so I'm not 100% sure this works on Python 2

    0 讨论(0)
  • 2021-01-14 21:39

    threading.Timer inherits threading.Thread. Thread object is not reusable. You can create Timer instance for each call.

    from threading import Timer
    import time
    
    class RepeatableTimer(object):
        def __init__(self, interval, function, args=[], kwargs={}):
            self._interval = interval
            self._function = function
            self._args = args
            self._kwargs = kwargs
        def start(self):
            t = Timer(self._interval, self._function, *self._args, **self._kwargs)
            t.start()
    
    def hello():
        print "hello"
    
    a=RepeatableTimer(3,hello,())
    a.start()
    time.sleep(4)
    a.start()
    
    0 讨论(0)
提交回复
热议问题