Cancellable threading.Timer in Python

后端 未结 4 1458
南旧
南旧 2020-12-02 13:15

I am trying to write a method that counts down to a given time and unless a restart command is given, it will execute the task. But I don\'t think Python threading.Tim

相关标签:
4条回答
  • 2020-12-02 13:47

    You would call the cancel method after you start the timer:

    import time
    import threading
    
    def hello():
        print "hello, world"
        time.sleep(2)
    
    t = threading.Timer(3.0, hello)
    t.start()
    var = 'something'
    if var == 'something':
        t.cancel()
    

    You might consider using a while-loop on a Thread, instead of using a Timer.
    Here is an example appropriated from Nikolaus Gradwohl's answer to another question:

    import threading
    import time
    
    class TimerClass(threading.Thread):
        def __init__(self):
            threading.Thread.__init__(self)
            self.event = threading.Event()
            self.count = 10
    
        def run(self):
            while self.count > 0 and not self.event.is_set():
                print self.count
                self.count -= 1
                self.event.wait(1)
    
        def stop(self):
            self.event.set()
    
    tmr = TimerClass()
    tmr.start()
    
    time.sleep(3)
    
    tmr.stop()
    
    0 讨论(0)
  • 2020-12-02 13:51

    The threading.Timer class does have a cancel method, and although it won't cancel the thread, it will stop the timer from actually firing. What actually happens is that the cancel method sets a threading.Event, and the thread actually executing the threading.Timer will check that event after it's done waiting and before it actually executes the callback.

    That said, timers are usually implemented without using a separate thread for each one. The best way to do it depends on what your program is actually doing (while waiting for this timer), but anything with an event loop, like GUI and network frameworks, all have ways to request a timer that is hooked into the eventloop.

    0 讨论(0)
  • 2020-12-02 14:01

    I'm not sure if I understand correctly. Do you want to write something like in this example?

    >>> import threading
    >>> t = None
    >>> 
    >>> def sayHello():
    ...     global t
    ...     print "Hello!"
    ...     t = threading.Timer(0.5, sayHello)
    ...     t.start()
    ... 
    >>> sayHello()
    Hello!
    Hello!
    Hello!
    Hello!
    Hello!
    >>> t.cancel()
    >>>
    
    0 讨论(0)
  • 2020-12-02 14:05

    Inspired by above post. Cancelable and Resetting Timer in Python. It uses thread.
    Features: Start, Stop, Restart, callback function.
    Input: Timeout, sleep_chunk values, and callback_function.
    Can use or inherit this class in any other program. Can also pass arguments to the callback function.
    Timer should respond in middle also. Not just after completion of full sleep time. So instead of using one full sleep, using small chunks of sleep and kept checking event object in loop.

    import threading
    import time
    
    class TimerThread(threading.Thread):
        def __init__(self, timeout=3, sleep_chunk=0.25, callback=None, *args):
            threading.Thread.__init__(self)
    
            self.timeout = timeout
            self.sleep_chunk = sleep_chunk
            if callback == None:
                self.callback = None
            else:
                self.callback = callback
            self.callback_args = args
    
            self.terminate_event = threading.Event()
            self.start_event = threading.Event()
            self.reset_event = threading.Event()
            self.count = self.timeout/self.sleep_chunk
    
        def run(self):
            while not self.terminate_event.is_set():
                while self.count > 0 and self.start_event.is_set():
                    # print self.count
                    # time.sleep(self.sleep_chunk)
                    # if self.reset_event.is_set():
                    if self.reset_event.wait(self.sleep_chunk):  # wait for a small chunk of timeout
                        self.reset_event.clear()
                        self.count = self.timeout/self.sleep_chunk  # reset
                    self.count -= 1
                if self.count <= 0:
                    self.start_event.clear()
                    #print 'timeout. calling function...'
                    self.callback(*self.callback_args)
                    self.count = self.timeout/self.sleep_chunk  #reset
    
        def start_timer(self):
            self.start_event.set()
    
        def stop_timer(self):
            self.start_event.clear()
            self.count = self.timeout / self.sleep_chunk  # reset
    
        def restart_timer(self):
            # reset only if timer is running. otherwise start timer afresh
            if self.start_event.is_set():
                self.reset_event.set()
            else:
                self.start_event.set()
    
        def terminate(self):
            self.terminate_event.set()
    
    #=================================================================
    def my_callback_function():
        print 'timeout, do this...'
    
    timeout = 6  # sec
    sleep_chunk = .25  # sec
    
    tmr = TimerThread(timeout, sleep_chunk, my_callback_function)
    tmr.start()
    
    quit = '0'
    while True:
        quit = raw_input("Proceed or quit: ")
        if quit == 'q':
            tmr.terminate()
            tmr.join()
            break
        tmr.start_timer()
        if raw_input("Stop ? : ") == 's':
            tmr.stop_timer()
        if raw_input("Restart ? : ") == 'r':
            tmr.restart_timer()
    
    0 讨论(0)
提交回复
热议问题