一个精确的python睡眠函数
我试过time.sleep(),但它的准确性完全是垃圾。考虑这个循环,例如:一个精确的python睡眠函数,python,real-time,Python,Real Time,我试过time.sleep(),但它的准确性完全是垃圾。考虑这个循环,例如: for i in range(10000000): print(i) sleep(.334) 注意它打印的数字。如果它有点像我的电脑,它甚至一点都不正常。这个函数应该是准确的吗?我是否在我的系统中发现了一个bug 如果这个函数不应该是精确的,那么哪个函数更精确呢?如果您只是查看输出,缓冲可能会使它看起来有点不稳定。您可以尝试显式地刷新输出,但随后您也将受制于显示输出的内容。我甚至可能冒昧地猜测,您在浏
for i in range(10000000):
print(i)
sleep(.334)
注意它打印的数字。如果它有点像我的电脑,它甚至一点都不正常。这个函数应该是准确的吗?我是否在我的系统中发现了一个bug
如果这个函数不应该是精确的,那么哪个函数更精确呢?如果您只是查看输出,缓冲可能会使它看起来有点不稳定。您可以尝试显式地刷新输出,但随后您也将受制于显示输出的内容。我甚至可能冒昧地猜测,您在浏览器中使用的是Jupyter笔记本,它在更新时也会有大量缓冲/延迟 另一个问题是,如果您希望每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
对我来说,它给出了如下信息:
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中运行这个,这可能会有帮助),但不会在运行时累积错误
但真正的问题是您想做什么?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
此外,如果您不介意将所有代码放在函数中,您可以使用decorator函数:
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()
我建议使用第一种方法,因为将所有代码放在函数中可能会非常低效
注意:如果您正在执行的代码比您尝试等待的时间长,那么这将不起作用。它在您的情况下应该可以工作,因为打印时间不应该超过0.334秒。好的,这次我真的解决了这个问题。这不是IO缓冲,也不是调用print()或某些可怕的操作系统特定调度巫术所需的时间。这一直是我的终点站。(…m.night shyamalan twist…)具体来说,
xfce4终端
,但在尝试了其他七个终端后,我发现lxterminal
存在完全相同的问题。它们都是基于VTE的,但也有其他基于VTE的模拟器没有问题,比如terminator
和gnome-terminal
。不管怎样,我换了终端,问题就解决了
我敢打赌,没有使用这两个有问题的终端中任何一个的人都在想我到底在说什么。你看到打印的是什么数字?你期望的是什么数字?它打印的是什么数字?我跑步的时候没注意到任何问题你想睡1/3秒吗?文档说明了为什么需要更长或更短的时间。您是否更关心在特定时间间隔内准确发生的事情(例如,在程序开始后准确地每1/3秒发生一次),还是更关心在事情发生后等待一段时间(例如,在事情发生后等待1/3秒)?大多数“正常”计算机您不能期望操作需要精确的时间,因为操作系统可以随时抢占您的应用程序。不仅如此,而且
print()
也需要时间,因为for
循环需要时间,这一点(通过设计)很难解释。如果您关心精确的计时,您可能需要一个缓冲区,但更可能的情况是您正在尝试解决—试着问这个问题。我正在使用的终端(xfce4终端)和所有喜欢它的终端都在换行上缓冲,所以这不是问题。这些终端非常适合在接收数据时实时显示数据。打印几乎立即执行,或者至少在50毫秒以下执行。这不是问题。但是使用while
循环会显著地占用大量CPU!当我使用time.sleep
方法时,我只看到Python使用了大约39%,这是0%(与任务管理器得到的一样精确)!