可变延时定时器

Timer for variable time delay

我想要一个计时器(目前使用Python 3.8)首先检查系统时间或海军天文台时钟,这样它就可以随时启动并与00秒同步。

我只对系统时钟或海军天文台的秒数感兴趣。在每一分钟的顶部,即当秒数 = 00 时,我需要将数据写入 DataFrame 或数据库,然后再睡 60 秒。

我首先检查了系统时间,确定了从 00 秒开始的时间,并设置了第一个延迟时间。之后它应该延迟或休眠 60 秒,然后再次 运行。数据在不断变化,但此时我只需要每 60 秒写入一次数据,也希望它能够使用其他时间范围,如 5 分钟、15 分钟等,但是一旦第一个完成,另一个时间框架会很容易。

这是我的蹩脚尝试,它 运行 几次迭代然后退出,我确信它不是很有效

def time_delay():
    sec = int(time.strftime('%S'))
    if sec != 0:
        wait_time = 60 - sec
        time.sleep(wait_time)
        sec = int(time.strftime('%S'))
        wait_time = 60 - sec
        
    elif time.sleep(60):
        time_delay()    

这将在秒数为 0 时调用一个函数:

def time_loop(job):
    while True:
        if int(time.time()) % 60 == 0:
            job()
        time.sleep( 1 )

这并不像您想要的那样普遍,正如我在评论中所说,由于涉及固有的开销,不可能与时间源完全同步(但您可以非常接近)。

下面所做的是定义一个 Thread 子类,该子类可用于以固定间隔调用用户指定的函数,从系统时钟的整秒数开始。

它首先延迟到指定秒数的下一个 multiple 发生,然后从该点开始每隔 interval 秒调用一次函数,同时补偿执行指定函数的时间很长。

from threading import Thread, Event
import time


class TimedCalls(Thread):
    def __init__(self, func, interval, multiple):
        super().__init__()
        self.func = func
        self.interval = interval
        if multiple == 0:
            self.multiple = 60  # Avoid ZeroDivisionError.
        else:
            self.multiple = multiple
        self.stopped = Event()

    def cancel(self):
        self.stopped.set()

    def start(self):
        # Initially sync to a whole multiple of the interval.
        frac = self.multiple  - (time.time() % self.multiple)
        time.sleep(frac)
        super().start()

    def run(self):
        next_call = time.time()
        while not self.stopped.is_set():
            self.func(next_call)  # Target activity.
            next_call = next_call + self.interval
            # Block until beginning of next interval (unless canceled).
            self.stopped.wait(next_call - time.time())


def my_function(tm):
    print(f"{tm} → {time.strftime('%H:%M:%S', time.localtime(tm))}")


# Call function every 10 sec starting at multiple of 5 secs
timed_calls = TimedCalls(my_function, 10, 5)
timed_calls.start()
try:
    time.sleep(125)  # Let the timed calls occur.
finally:
    timed_calls.cancel()
print('done')

示例输出:

1617662925.0018559 → 15:48:45
1617662935.0018559 → 15:48:55
1617662945.0018559 → 15:49:05
1617662955.0018559 → 15:49:15
1617662965.0018559 → 15:49:25
1617662975.0018559 → 15:49:35
1617662985.0018559 → 15:49:45
1617662995.0018559 → 15:49:55
1617663005.0018559 → 15:50:05
1617663015.0018559 → 15:50:15
1617663025.0018559 → 15:50:25
1617663035.0018559 → 15:50:35
1617663045.0018559 → 15:50:45
done