pythonで一定間隔ごとに処理をしたい場合、以下のように単純にsleepしてしまうと、一定間隔でなくなってしまう。
bad.py
import time
def worker():
print(time.time())
time.sleep(8)
interval = 5
while True:
worker()
time.sleep(interval)
実際にこの例だと5秒おきに実行したかったのに、13秒おきに実行されてしまう。
1518294594.6087666
1518294607.611248
1518294620.6149857
以下のようにベースとなる時間を決めてそこからの時間差分を考慮するとできる。
schedule.py
import time
import threading
def worker():
print(time.time())
time.sleep(8)
def schedule(interval, f, wait=True):
base_time = time.time()
next_time = 0
while True:
t = threading.Thread(target=f)
t.start()
if wait:
t.join()
next_time = ((base_time - time.time()) % interval) or interval
time.sleep(next_time)
waitがTrueの場合、同時実行されるスレッドは1つのみとなり、待ち時間以内に処理が終わらなかったら次のタイムスロットまで待つ。
(この例だと、5秒以内に処理が終わらないので+5秒さらに待つ)
>>> schedule(5, worker)
1518295406.8357077
1518295416.849788
1518295426.8451777
waitがFalseの場合は、きっちり5秒ごとに実行される(複数スレッドになりうる)
>>> schedule(5, worker, False)
1518295478.5527058
1518295483.5534766
1518295488.5580828