【问题标题】:Run a python function every second每秒运行一个 python 函数
【发布时间】:2012-06-04 12:08:22
【问题描述】:

我想要的是能够每秒运行一个函数,与函数需要多长时间无关(它应该总是在一秒以下)。我考虑了许多选项,但不确定哪个最好。

如果我只使用延迟函数,它不会考虑函数运行所需的时间。

如果我对函数进行计时,然后从一秒中减去它并在延迟中弥补其余部分,则不会考虑时间计算。

我尝试使用 threading.timer(我不确定它是如何工作的),但它似乎确实比 1s 慢。

这是我尝试测试 threading.timer 的代码:

def update(i):
    sys.stdout.write(str(i)+'\r')
    sys.stdout.flush()
    print i
    i += 1
    threading.Timer(1, update, [i]).start()

有没有一种方法可以做到这一点与函数花费的时间长度无关?

【问题讨论】:

标签: python


【解决方案1】:

这样就可以了,而且它的准确性不会随着时间而漂移。

import time

start_time = time.time()
interval = 1
for i in range(20):
    time.sleep(start_time + i*interval - time.time())
    f()

【讨论】:

【解决方案2】:

实际上不应该使用使用 threading.Timer 的方法(参见下面的代码),因为每个间隔都会启动一个新线程,并且这个循环永远无法完全停止。

# as seen here: https://stackoverflow.com/a/3393759/1025391
def update(i):
  threading.Timer(1, update, [i+1]).start()
  # business logic here

如果您想要一个后台循环,最好启动一个运行循环的新线程,如另一个答案中所述。它能够接收停止信号,s.t.您最终可以join() 线程。

This related answer 似乎是实现这一点的一个很好的起点。

【讨论】:

  • @lucid_dreamer 关于递归深度的推理不正确(新线程不会增加递归深度)。但我同意这不是理想的实现方式。反复启动新线程以及最终无法停止循环的原因。
  • 我明白了。不过还是很奇怪,他报了一个引用错误“RuntimeError: maximum recursion depth exceeded”。
【解决方案3】:

这样怎么样:每次运行后,睡眠(1.0 - launch interval) 秒。您可以通过更改while True: 来更改终止条件。虽然如果你的函数运行时间超过 1 秒,就会出错。

from time import time, sleep

while True:
    startTime = time()
    yourFunction()
    endTime = time()-startTime
    sleep(1.0-endTime)

【讨论】:

    【解决方案4】:

    线程可能是一个不错的选择。基本概念如下。

    import threading
    
    def looper():    
        # i as interval in seconds    
        threading.Timer(i, looper).start()    
        # put your action here
        foo()
    
    #to start 
    looper()
    

    【讨论】:

      【解决方案5】:

      如果f() 总是花费不到一秒的时间,那么就在一秒的边界上运行它(没有漂移):

      import time
      
      while True:
          time.sleep(1 - time.monotonic() % 1)      
          f()
      

      创意来自@Dave Rove's answer to a similar question

      要了解它的工作原理,请考虑一个示例:

      1. time.monotonic() 返回13.7 并调用time.sleep(0.3)
      2. f() 被调用(±一些错误)14 秒(因为 time.monotonic() 纪元)
      3. f() 正在运行,它需要 0.1 (
      4. time.monotonic()14.1 秒左右返回,time.sleep(0.9) 被调用
      5. 第 2 步在 15 秒左右重复(从 time.monotonic() 纪元开始)
      6. f() 已运行,需要 0.3 (
      7. time.monotonic()15.3 附近返回,time.sleep(0.7) 被调用
      8. f()16 秒左右被调用并重复循环。

      在每一步中,f() 在一秒的边界上被调用(根据time.monotonic() 计时器)。错误不会累积。没有漂移。

      另请参阅:How to run a function periodically in python (using tkinter)

      【讨论】:

        【解决方案6】:

        我想推荐以下代码。如果需要,您可以将 True 替换为任何条件。

        while True:
        time.sleep(1) #sleep for 1 second
        func()    #function you want to trigger
        

        告诉我它是否有效。

        【讨论】:

          猜你喜欢
          • 2014-03-05
          • 2021-11-13
          • 2019-03-11
          • 2020-07-15
          • 2012-01-09
          • 1970-01-01
          • 2014-12-24
          • 2022-01-14
          相关资源
          最近更新 更多