Python 周期性循环惯用语?

4
我有一个单位的任务,我希望每N秒执行一次。如果我使用简单的方法:
minute = 60
while True:
    doSomeWork()
    time.sleep(minute)

根据doSomeWork()所需的时间长短,真正的循环周期将是一分钟加上那个时间。如果doSomeWork()所需时间不确定,那么工作的周期就更加不可预测。

我想做的事情类似于这样

minute = 60
start = time.process_time() #? i can imagine using this, but maybe there's something better?
while True:
    doSomeWork()
    start += minute
    sleep_until(start) #? this is the function I'm in search of

我正在使用Python 3.3。

更新:

在Linux/OSX上,我可以使用信号中的itimer来实现我想要的功能:

import signal
import datetime

def tick(_, __):
    # doSomeWork()
    print(datetime.datetime.now())

signal.setitimer(signal.ITIMER_REAL, 60, 60)
signal.signal(signal.SIGALRM, tick)

while True:
    signal.pause()

看起来为Python3.4开发的郁金香工具也会使这个过程变得容易。


相关:https://dev59.com/onE95IYBdhLWcg3wPbZ7 - David Z
1个回答

5

sleep_until(timestamp)基本上是time.sleep(timestamp - time.time())

实际上,您的代码很好(确保不将负时间传递给睡眠仍然是一个好主意):

import time

minute = 60
next_time = time.time()
while True:
    doSomeWork()
    next_time += minute
    sleep_time = next_time - time.time()
    if sleep_time > 0:
        time.sleep(sleep_time)

我个人会创建一个60秒间隔的时间戳生成器并使用它:
import time
import itertools

minute = 60

for next_time in itertools.count(time.time() + minute, minute):
    doSomeWork()
    sleep_time = next_time - time.time()
    if sleep_time > 0:
        time.sleep(sleep_time)

这样做是否仍会引入一些偏差(尽管较小)?计算已经消耗的时间表达式,加上排队剩余睡眠所需的时间,将消耗一些未计算的时间。 - Travis Griggs
@PavelAnossov 我猜这是原则问题。我在许多其他环境(语言/库)中都使用了这种习惯用法。一旦你掌握了这个技巧,你就不必担心这部分需要多长时间,也不必计算它有多重要。 - Travis Griggs
我怀疑根据这里的评论,也许Python没有这个功能,这让我感到惊讶。 - Travis Griggs
非常好。我会保留第二个版本。 - user4815162342
3
如果 doSomeWork 花费超过一分钟的时间,那么下一个计划时间会在当前时间之前,此时您可能需要跳过 sleep。由于您正在使用 itertools,因此可以使用 for 替代 whilefor next_time in schedule: if next_time >= time.time(): sleep(next_time - time.time()) ... - user4815162342
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接