我编写了许多依赖于精确定期方法调用的代码。我一直在使用Python的futures
库将调用提交到运行时的线程池,并在循环调用之间休眠:
executor = ThreadPoolExecutor(max_workers=cpu_count())
def remote_call():
# make a synchronous bunch of HTTP requests
def loop():
while True:
# do work here
executor.submit(remote_call)
time.sleep(60*5)
然而,我注意到这个实现在长时间运行后引入了一些漂移(例如,我运行此代码大约10个小时,并注意到大约7秒的漂移)。对于我的工作,我需要在确切的秒上运行,毫秒甚至会更好。有些人指出我asyncio
("Fire and forget" python async/await),但我无法在Python 2.7中使用它。
我不是在寻找黑客。我真正想要的是类似于Go time.Tick
或Netty' HashedWheelTimer
。
答案 0 :(得分:5)
Python没有类似的东西。您需要手动调整您的睡眠时间以计算工作时间。
你可以把它折叠成迭代器,就像Go的time.Tick
的频道一样:
import itertools
import time
import timeit
def tick(interval, initial_wait=False):
# time.perf_counter would probably be more appropriate on Python 3
start = timeit.default_timer()
if not initial_wait:
# yield immediately instead of sleeping
yield
for i in itertools.count(1):
time.sleep(start + i*interval - timeit.default_timer())
yield
for _ in tick(300):
# Will execute every 5 minutes, accounting for time spent in the loop body.
do_stuff()
请注意,当您开始迭代时,上述自动收报机会开始计时,而不是在您调用tick
时,如果您尝试启动自动收报机并将其保存以供日后使用。此外,它不发送时间,如果接收器很慢,它不会丢弃滴答。如果需要,您可以自行调整所有这些。