有没有办法阻止计时器蠕变?

时间:2017-07-29 00:27:10

标签: python timer python-multithreading

我正在寻找一种每秒运行一个方法的方法,无论运行多长时间。在寻求帮助时,我遇到了

Run certain code every n seconds

并在尝试中发现它无法正常工作。它似乎有我试图避免的问题:漂移。我尝试添加一个"睡眠(0.5)"在打印之后,它实际上减慢了循环,并且间隔保持在1.003(大致)秒。

有没有办法解决这个问题,做我想做的事情?

(venv) 20170728-153445 mpeck@bilbo:~/dev/whiskerlabs/aphid/loadtest$ cat a.py
import threading
import time
def woof():
  threading.Timer(1.0, woof).start()
  print "Hello at %s" % time.time()
woof()
(venv) 20170728-153449 mpeck@bilbo:~/dev/whiskerlabs/aphid/loadtest$ python a.py
Hello at 1501281291.84
Hello at 1501281292.85
Hello at 1501281293.85
Hello at 1501281294.85
Hello at 1501281295.86
Hello at 1501281296.86
Hello at 1501281297.86
Hello at 1501281298.87
Hello at 1501281299.87
Hello at 1501281300.88
Hello at 1501281301.88
Hello at 1501281302.89
Hello at 1501281303.89
Hello at 1501281304.89
Hello at 1501281305.89
Hello at 1501281306.9
Hello at 1501281307.9
Hello at 1501281308.9
Hello at 1501281309.91
Hello at 1501281310.91
Hello at 1501281311.91
Hello at 1501281312.91
Hello at 1501281313.92
Hello at 1501281314.92
Hello at 1501281315.92
Hello at 1501281316.93

2 个答案:

答案 0 :(得分:1)

  1. 如果每次实际上不需要新线程,请不要使用threading.Timer;在循环中定期运行一个函数sleep(可能在一个单独的线程中)。

  2. 无论您使用哪种方法来安排下一次执行,都不要等待您用作间隔的确切时间 - 其他语句的执行需要时间,因此您可以看到结果是漂移。相反,记下变量中的初始时间,并在每次迭代时计算下次您想要计划执行和睡眠时间之间的差异。

    interval = 1.
    next_t = time.time()
    while True:
        next_t += interval
        time.sleep(next_t - time.time())
        # do whatever you want to do 
    

    (当然你可以改进它以获得更好的整体准确性,但这至少应避免漂移)

答案 1 :(得分:0)

我非常确定该代码的问题是它需要Python一些时间(显然大约为.3s)来执行对函数woof的调用,实例化一个新的threading.Timer对象,并打印当前时间。所以基本上,在你第一次调用函数和创建threading.Timer之后,Python等待1s,然后调用函数woof(一个十分左右),创建一个新的{{1}对象(至少是另一个decisecond),最后以一些延迟打印当前时间。

实际上每秒运行一个程序的解决方案似乎是Twisted库,如this other post所述,但我自己并没有真正尝试过......

编辑:我会将问题标记为可能重复但我显然没有足够的声誉来做到这一点......如果有人能够这样做至少这样做我提供的链接,很酷:)