【问题标题】:Running Python function at defined intervals以定义的时间间隔运行 Python 函数
【发布时间】:2019-11-03 21:25:53
【问题描述】:

我有一个 Python 循环,应该每分钟运行一次,进行一些数据处理并休眠到下一分钟。然而,处理需要的时间是可变的,有时在没有太多事情可做时接近于零,有时甚至需要 10 或 20 秒。

为了弥补这一点,我测量运行处理所需的时间,如下所示:

while True:
  time_start = time.time()
  do_something()                        # <-- This takes unknown time
  time_spent = time.time() - time_start
  time.sleep(60 - time_spent)

它有点工作,但几天后它仍然会漂移几秒钟。我猜它发生在计算机(小树莓派)很忙并延迟循环的开始时,然后一切都开始溜走。

我不需要do_something() 每分钟执行准确,所以不需要实时操作系统或类似的东西,但我不希望一个延迟启动影响所有后续启动要么。

是否有某种调度程序可以以预定义的速率运行我的函数?或者一些更聪明的方法来弥补偶尔的延迟?

【问题讨论】:

  • 如果你真的想要这种并发,我认为你必须使用线程。一个线程作为计时器,另一个作为工作线程。
  • @phalanx 如果计时器线程被延迟/溜走怎么办?我认为这与我使用的时间戳补偿方法没有什么不同。除非你的意思是一些(硬件)计划的计时器?
  • time.sleep(60 - time.time() % 60) 作为最后一行怎么样?
  • @quamrana 谢谢,但对于我所追求的简单固定速率触发器来说,这是一个过于复杂的解决方案。我下面的解决方案似乎适用于我的情况。

标签: python scheduled-tasks


【解决方案1】:

稍微玩一下循环,这似乎工作得很好。诀窍是在循环开始之前记录一次开始时间,而不是每次迭代。这样一来,延迟的开始就不会影响以后的任何开始。

rate_sec = 60
time_start = time.time()

while True:
    print("{}".format(datetime.now()))

    # Emulate processing time 0s to 20s
    time.sleep(random.randint(0, 20))

    # Sleep until the next 'rate_sec' multiple
    delay = rate_sec - (time.time() - time_start) % rate_sec
    time.sleep(delay)

【讨论】:

    【解决方案2】:

    睡眠是您项目的先决条件吗?我的意思是,如果您想每约 1 分钟运行一次任务,则无需阻止您的处理。

    由于您使用的是 Raspberry Pi,因此您可以(并且可能应该)使用 crontab。

    这将为您提供最大的灵活性,并让您不会让计算机处于空闲状态。

    为此,请使用

    打开您的 cron 选项卡
    crontab -e
    

    并添加以下条目

    * * * * * /usr/bin/env python3 /path/to/script.py
    

    【讨论】:

    • 我正在考虑这个问题,但是在 RPi 上启动过程和校准需要花费几分钟,所以很遗憾,这不是一个选项。可以在程序启动时在 RPi 启动期间执行此操作,但不是在每次迭代时执行此操作。不过感谢您的建议:)
    猜你喜欢
    • 2020-12-13
    • 1970-01-01
    • 1970-01-01
    • 2013-08-04
    • 2019-01-07
    • 2022-11-30
    • 1970-01-01
    • 1970-01-01
    • 2021-05-31
    相关资源
    最近更新 更多