What is the best way to repeatedly execute a function every x seconds?

后端 未结 18 2696
不知归路
不知归路 2020-11-21 06:04

I want to repeatedly execute a function in Python every 60 seconds forever (just like an NSTimer in Objective C). This code will run as a daemon and is effectively like call

18条回答
  •  盖世英雄少女心
    2020-11-21 06:16

    Here's an adapted version to the code from MestreLion. In addition to the original function, this code:

    1) add first_interval used to fire the timer at a specific time(caller need to calculate the first_interval and pass in)

    2) solve a race-condition in original code. In the original code, if control thread failed to cancel the running timer("Stop the timer, and cancel the execution of the timer’s action. This will only work if the timer is still in its waiting stage." quoted from https://docs.python.org/2/library/threading.html), the timer will run endlessly.

    class RepeatedTimer(object):
    def __init__(self, first_interval, interval, func, *args, **kwargs):
        self.timer      = None
        self.first_interval = first_interval
        self.interval   = interval
        self.func   = func
        self.args       = args
        self.kwargs     = kwargs
        self.running = False
        self.is_started = False
    
    def first_start(self):
        try:
            # no race-condition here because only control thread will call this method
            # if already started will not start again
            if not self.is_started:
                self.is_started = True
                self.timer = Timer(self.first_interval, self.run)
                self.running = True
                self.timer.start()
        except Exception as e:
            log_print(syslog.LOG_ERR, "timer first_start failed %s %s"%(e.message, traceback.format_exc()))
            raise
    
    def run(self):
        # if not stopped start again
        if self.running:
            self.timer = Timer(self.interval, self.run)
            self.timer.start()
        self.func(*self.args, **self.kwargs)
    
    def stop(self):
        # cancel current timer in case failed it's still OK
        # if already stopped doesn't matter to stop again
        if self.timer:
            self.timer.cancel()
        self.running = False
    

提交回复
热议问题