Python threading.timer - repeat function every 'n' seconds

前端 未结 13 1272
挽巷
挽巷 2020-11-22 09:45

I want to fire off a function every 0.5 seconds and be able to start and stop and reset the timer. I\'m not too knowledgeable of how Python threads work and am having diffic

相关标签:
13条回答
  • 2020-11-22 10:18

    In addition to the above great answers using Threads, in case you have to use your main thread or prefer an async approach - I wrapped a short class around aio_timers Timer class (to enable repeating)

    import asyncio
    from aio_timers import Timer
    
    class RepeatingAsyncTimer():
        def __init__(self, interval, cb, *args, **kwargs):
            self.interval = interval
            self.cb = cb
            self.args = args
            self.kwargs = kwargs
            self.aio_timer = None
            self.start_timer()
        
        def start_timer(self):
            self.aio_timer = Timer(delay=self.interval, 
                                   callback=self.cb_wrapper, 
                                   callback_args=self.args, 
                                   callback_kwargs=self.kwargs
                                  )
        
        def cb_wrapper(self, *args, **kwargs):
            self.cb(*args, **kwargs)
            self.start_timer()
    
    
    from time import time
    def cb(timer_name):
        print(timer_name, time())
    
    print(f'clock starts at: {time()}')
    timer_1 = RepeatingAsyncTimer(interval=5, cb=cb, timer_name='timer_1')
    timer_2 = RepeatingAsyncTimer(interval=10, cb=cb, timer_name='timer_2')
    

    clock starts at: 1602438840.9690785

    timer_1 1602438845.980087

    timer_2 1602438850.9806316

    timer_1 1602438850.9808934

    timer_1 1602438855.9863033

    timer_2 1602438860.9868324

    timer_1 1602438860.9876585

    0 讨论(0)
  • 2020-11-22 10:27

    The best way is to start the timer thread once. Inside your timer thread you'd code the following

    class MyThread(Thread):
        def __init__(self, event):
            Thread.__init__(self)
            self.stopped = event
    
        def run(self):
            while not self.stopped.wait(0.5):
                print("my thread")
                # call a function
    

    In the code that started the timer, you can then set the stopped event to stop the timer.

    stopFlag = Event()
    thread = MyThread(stopFlag)
    thread.start()
    # this will stop the timer
    stopFlag.set()
    
    0 讨论(0)
  • 2020-11-22 10:29

    I had to do this for a project. What I ended up doing was start a separate thread for the function

    t = threading.Thread(target =heartbeat, args=(worker,))
    t.start()
    

    ****heartbeat is my function, worker is one of my arguments****

    inside of my heartbeat function:

    def heartbeat(worker):
    
        while True:
            time.sleep(5)
            #all of my code
    

    So when I start the thread the function will repeatedly wait 5 seconds, run all of my code, and do that indefinitely. If you want to kill the process just kill the thread.

    0 讨论(0)
  • 2020-11-22 10:30

    Improving a little on Hans Then's answer, we can just subclass the Timer function. The following becomes our entire "repeat timer" code, and it can be used as a drop-in replacement for threading.Timer with all the same arguments:

    from threading import Timer
    
    class RepeatTimer(Timer):
        def run(self):
            while not self.finished.wait(self.interval):
                self.function(*self.args, **self.kwargs)
    

    Usage example:

    def dummyfn(msg="foo"):
        print(msg)
    
    timer = RepeatTimer(1, dummyfn)
    timer.start()
    time.sleep(5)
    timer.cancel()
    

    produces the following output:

    foo
    foo
    foo
    foo
    

    and

    timer = RepeatTimer(1, dummyfn, args=("bar",))
    timer.start()
    time.sleep(5)
    timer.cancel()
    

    produces

    bar
    bar
    bar
    bar
    
    0 讨论(0)
  • 2020-11-22 10:30

    I have implemented a class that works as a timer.

    I leave the link here in case anyone needs it: https://github.com/ivanhalencp/python/tree/master/xTimer

    0 讨论(0)
  • 2020-11-22 10:30

    I have come up with another solution with SingleTon class. Please tell me if any memory leakage is here.

    import time,threading
    
    class Singleton:
      __instance = None
      sleepTime = 1
      executeThread = False
    
      def __init__(self):
         if Singleton.__instance != None:
            raise Exception("This class is a singleton!")
         else:
            Singleton.__instance = self
    
      @staticmethod
      def getInstance():
         if Singleton.__instance == None:
            Singleton()
         return Singleton.__instance
    
    
      def startThread(self):
         self.executeThread = True
         self.threadNew = threading.Thread(target=self.foo_target)
         self.threadNew.start()
         print('doing other things...')
    
    
      def stopThread(self):
         print("Killing Thread ")
         self.executeThread = False
         self.threadNew.join()
         print(self.threadNew)
    
    
      def foo(self):
         print("Hello in " + str(self.sleepTime) + " seconds")
    
    
      def foo_target(self):
         while self.executeThread:
            self.foo()
            print(self.threadNew)
            time.sleep(self.sleepTime)
    
            if not self.executeThread:
               break
    
    
    sClass = Singleton()
    sClass.startThread()
    time.sleep(5)
    sClass.getInstance().stopThread()
    
    sClass.getInstance().sleepTime = 2
    sClass.startThread()
    
    0 讨论(0)
提交回复
热议问题