Lo uso para causar 60 eventos por hora y la mayoría de los eventos ocurren en la misma cantidad de segundos después de todo el minuto:
import math
import time
import random
TICK = 60 # one minute tick size
TICK_TIMING = 59 # execute on 59th second of the tick
TICK_MINIMUM = 30 # minimum catch up tick size when lagging
def set_timing():
now = time.time()
elapsed = now - info['begin']
minutes = math.floor(elapsed/TICK)
tick_elapsed = now - info['completion_time']
if (info['tick']+1) > minutes:
wait = max(0,(TICK_TIMING-(time.time() % TICK)))
print ('standard wait: %.2f' % wait)
time.sleep(wait)
elif tick_elapsed < TICK_MINIMUM:
wait = TICK_MINIMUM-tick_elapsed
print ('minimum wait: %.2f' % wait)
time.sleep(wait)
else:
print ('skip set_timing(); no wait')
drift = ((time.time() - info['begin']) - info['tick']*TICK -
TICK_TIMING + info['begin']%TICK)
print ('drift: %.6f' % drift)
info['tick'] = 0
info['begin'] = time.time()
info['completion_time'] = info['begin'] - TICK
while 1:
set_timing()
print('hello world')
#random real world event
time.sleep(random.random()*TICK_MINIMUM)
info['tick'] += 1
info['completion_time'] = time.time()
Dependiendo de las condiciones reales, puede obtener garrapatas de longitud:
60,60,62,58,60,60,120,30,30,60,60,60,60,60...etc.
pero al cabo de 60 minutos tendrás 60 ticks; y la mayoría de ellos ocurrirán en el desplazamiento correcto al minuto que prefiera.
En mi sistema obtengo una deriva típica de <1/20 de segundo hasta que surge la necesidad de corrección.
La ventaja de este método es la resolución de la deriva del reloj; lo que puede causar problemas si está haciendo cosas como agregar un elemento por marca y espera 60 elementos agregados por hora. No tener en cuenta la deriva puede causar indicaciones secundarias, como promedios móviles, para considerar datos demasiado profundos en el pasado, lo que resulta en una salida defectuosa.