一个准确的python睡眠功能

时间:2017-12-10 01:36:51

标签: python real-time

我已经尝试过time.sleep(),但它的准确性是完全垃圾。考虑这个循环,例如:

for i in range(10000000):
    print(i)
    sleep(.334)

观看它打印的数字。如果它像我的电脑一样,它甚至不是常规的。这个功能应该准确吗?我在系统中的某个地方发现了一个错误吗?

如果这个功能不准确,哪个功能更准确?

3 个答案:

答案 0 :(得分:1)

如果您只是查看输出,缓冲可能会让它看起来有点紧张。您可以尝试显式刷新输出,但是您也可以使用任何显示输出的内容。我甚至可能会猜到你在浏览器中使用了Jupyter Notebook,它在更新时也会有一堆缓冲/延迟。

另一个问题是,如果您希望每1/3秒运行一次,那么您将遇到累积错误。运行循环需要一点时间,打印一个值(打印将比其他部分花费更多的时间),然后再次开始睡眠。绕过这种方法的一种方法是,在你完成你想做的任何事情之后(我假设比计数更有趣的东西),计算直到下一个1/3秒的时间并且睡眠这段时间。类似的东西:

import random
import time

sleep_until = time.monotonic() + 1/3

for n in range(100):
    print(time.monotonic() % 100, n)
    time.sleep(random.random() / 4) # some "work"

    now = time.monotonic()
    if sleep_until > now:
        time.sleep(sleep_until - now)
    else:
        pass
        #print('task took too long')
    sleep_until += 1/3

对我来说,它给出了类似的东西:

48.34696656104643 0
48.68041984003503 1
49.08346292399801 2
49.41925806296058 3
49.72542790300213 4
50.07280854298733 5
50.41882419097237 6
50.74827564903535 7
51.08352101803757 8
51.41813271504361 9
51.75208444998134 10
52.08399672002997 11
52.41870043799281 12

所以它反弹一点(我也在Jupyter中运行它,这可能会有所贡献),但在运行时不会出现错误。

真正的问题是你想做什么

答案 1 :(得分:0)

Python中的print语句需要时间才能运行。如果我需要一个Python程序在更长的时间内休眠,我使用datetime.timedelta代替while循环而不是time.sleep。这是我的代码:

from datetime import datetime, timedelta

startTime = datetime.now()
sleepTime = timedelta(seconds = 5)

# run code here

while startTime+sleepTime > datetime.now():
    pass

另外,如果您不介意将所有代码放入功能中,可以使用装饰器功能:

from datetime import datetime, timedelta

def sleep(time):
    def outer_wrap(func):
        def wrap(*args, **kwargs):
            startTime = datetime.now()
            sleepTime = timedelta(seconds = time)
            while startTime+sleepTime > datetime.now():
                pass
            func(*args, **kwargs)
        return wrap
    return outer_wrap

@sleep(5)
def c():
    # code goes here
    pass

c()

我会推荐第一种方法,因为将所有代码放入函数中效率非常低。

注意:如果您执行的代码比您尝试等待的时间长,则无效。它应该适用于您的情况,因为print不应超过0.334秒。

答案 2 :(得分:0)

好的,这一次我真的想通了这个。它不是IO缓冲,也不是调用print()或一些特定于操作系统的特定调度voodoo所需的时间。 这是我的终端。(...... m。晚上shyamalan扭曲......)具体来说,xfce4-terminal,虽然在尝试了其他七个终端之后,我找到了lxterminal有完全相同的问题。它们都是基于VTE的,但还有其他基于VTE的模拟器有问题,例如terminatorgnome-terminal。无论如何,我改变了终端,问题得到解决。

我打赌那些没有使用这两个有问题的终端中的任何一个的人都在想我到底在说什么。