Python - 准确的 time.sleep()

9
我正在处理一个精确计时非常关键的项目。我使用的是 Python 语言,使用了 timer.sleep() 函数。 我注意到由于调度问题(请参阅timer.sleep 文档),timer.sleep() 函数会添加额外的延迟。因此,随着程序运行时间越长,计时器就会变得越不准确。 是否有更准确的计时器或解决此问题的方法来暂停程序? 如果您能提供任何帮助将不胜感激。谢谢!

您尝试过为您的进程提供实时优先级吗?准确性是非确定性系统的问题,但是 Linux 可以非常接近大多数需求。您愿意容忍多少延迟?毫秒、微秒、纳秒?受时间限制的解决方案始终很难交付,并且非常脆弱,代码、内核或运行时的任何更改通常都会影响这些解决方案。 - geckos
3
你是否多次调用了 timer.sleep("程序运行时间越长,计时器的不准确性就越高")?如果是这样,你可以通过使用像 time.clock_gettime 这样的方法跟踪实际时间来校正睡眠时间。 - cdarke
@PeterWood 我正在使用Windows。好的,我会检查一下。谢谢 - Darren Christopher
@anishtain4 那么在Windows上基本上没有解决方案吗? - Darren Christopher
@DarrenChristopher:是的,但是 time.time() 只提供1秒的分辨率。 - cdarke
显示剩余16条评论
3个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
4

我曾经有一个类似上述解决方案的方法,但很快就变得非常占用处理器。这里提供一个占用处理器较高的想法和一个解决方法。

def processor_heavy_sleep(ms):  # fine for ms, starts to work the computer hard in second range.
    start = time.clock()
    end = start + ms /1000.
    while time.clock() < end:
        continue
    return start, time.clock()


def efficient_sleep(secs, expected_inaccuracy=0.5):  # for longer times
    start = time.clock()
    end = secs + start
    time.sleep(secs - expected_inaccuracy)
    while time.clock() < end:
        continue
    return start, time.clock()

efficient_sleep(5, 0.5) 的输出结果为:

  • (3.1999303695151594e-07, 5.0000003199930365)
  • (5.00005983869791, 10.00005983869791)
  • (10.000092477987678, 15.000092477987678)

这是在Windows上的运行结果。我正在进行100次循环的测试,以下是测试结果:

  • (485.003749358414, 490.003749358414)
  • (490.0037919174879, 495.0037922374809)
  • (495.00382903668014, 500.00382903668014)

睡眠时间保持准确,但调用总是有一点延迟。如果您需要精确每 xxx 秒调用到毫秒级别的调度程序,则需要另外考虑。


1
我的程序运行时间越长,计时器就越不准确。例如,期望0.5秒的延迟,实际使用time.sleep(0.5 - (start-end)),但仍未解决问题。您似乎在抱怨两个问题:1)timer.sleep()可能比您预期的时间更长,2)使用一系列timer.sleep()调用的固有漏洞。对于第一个问题,除非切换到实时操作系统,否则您无法做任何事情。底层操作系统调用被定义为至少睡眠所请求的时间。它们只保证您不会早醒;它们不保证您不会晚醒。至于第二个问题,您应该根据不变的时代来计算睡眠时间,而不是从唤醒时间开始。例如:
import time
import random

target = time.time()
def myticker():
    # Sleep for 0.5s between tasks, with no creep
    target += 0.5
    now = time.time()
    if target > now:
        time.sleep(target - now)


def main():
    previous = time.time()
    for _ in range(100):
        now = time.time()
        print(now - previous)
        previous = now
        # simulate some work
        time.sleep(random.random() / 10)  # Always < tick frequency
        # time.sleep(random.random())     # Not always < tick frequency
        myticker()

if __name__ == "__main__":
    main()

0

在 Linux 上工作却完全不了解 Windows,我可能有点天真,但是是否存在一些原因使你自己编写的 sleep 函数无法起作用?
类似于:

import time

def sleep_time():
    start_time = time.time()
    while (time.time() - start_time) < 0.0001:
        continue

end_time = time.time() + 60 # run for a minute
cnt = 0
while time.time() < end_time:
    cnt += 1
    print('sleeping',cnt)
    sleep_time()
    print('Awake')
print("Slept ",cnt," Times")

这会导致CPU崩溃。 - jbch
详细说明一下,忙等待有时是低级编程中的正确解决方案,但考虑到 OP 正在编写 Python,这显然不是他的情况。 - jbch
@jbch 的确是如此!考虑到OP的困境,必须在恶魔驱使时采取行动。这是一个选项,虽然有点繁重。 - Rolf of Saxony

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,