我可以给它浮点数,例如
time.sleep(0.5)
但它有多准确?如果我给它
time.sleep(0.05)
它真的会睡大约 50 毫秒吗?
time.sleep 函数的准确性取决于您的底层操作系统的睡眠准确性。对于像普通 Windows 这样的非实时操作系统,您可以休眠的最小时间间隔约为 10-13 毫秒。我在那个时间的几毫秒内看到了准确的睡眠,超过了最小 10-13 毫秒。
更新:就像下面引用的文档中提到的那样,通常在一个循环中进行睡眠,如果它早早唤醒你,它会确保重新进入睡眠状态。
我还应该提到,如果您运行的是 Ubuntu,您可以通过安装 rt 内核包(至少在 Ubuntu 10.04 LTS 中)来试用伪实时内核(带有 RT_PREEMPT 补丁集)。
编辑:更正非实时 Linux 内核的最小睡眠间隔更接近 1 毫秒然后 10 毫秒,但它以不确定的方式变化。
人们对操作系统和内核之间的差异是完全正确的,但是我在 Ubuntu 中没有看到任何粒度,而在 MS7 中我看到了 1 毫秒的粒度。建议 time.sleep 的不同实现,而不仅仅是不同的滴答率。顺便说一下,仔细检查表明 Ubuntu 中的粒度为 1μs,但这是由于我用于测量准确性的 time.time 函数。
从文档中:
另一方面,
time()
and的精度sleep()
优于它们的 Unix 等效项:时间以浮点数表示,time()
返回可用的最准确时间(gettimeofday
在可用的情况下使用 Unix),并且sleep()
将接受具有非零分数的时间(select
使用Unix实现这一点,如果有的话)。
更具体地说:_sleep()
在给定的秒数内暂停执行。该参数可以是一个浮点数,以指示更精确的睡眠时间。实际的挂起时间可能少于请求的时间,因为任何捕获的信号都将终止该
sleep()
信号的捕获例程的后续执行。此外,由于系统中其他活动的调度,暂停时间可能比请求的时间长任意量。
这是我对威尔伯特回答的后续行动:Mac OS X Yosemite 也是如此,因为它还没有被太多提及。
看起来很多时候它的睡眠时间大约是您请求时间的 1.25 倍,有时睡眠时间是您请求时间的 1 到 1.25 倍。它几乎从不(大约 1000 个样本中的两次)睡眠时间显着超过您请求时间的 1.25 倍。
此外(未明确显示)1.25 关系似乎保持得很好,直到您低于大约 0.2 毫秒,之后它开始变得有点模糊。此外,在请求的时间量超过 20 毫秒后,实际时间似乎比您请求的长约 5 毫秒。
同样,它在 OS X 中的实现似乎与sleep()
在 Windows 或任何 Linux 内核 Wilbert 使用的完全不同。
为什么不知道:
from datetime import datetime
import time
def check_sleep(amount):
start = datetime.now()
time.sleep(amount)
end = datetime.now()
delta = end-start
return delta.seconds + delta.microseconds/1000000.
error = sum(abs(check_sleep(0.050)-0.050) for i in xrange(100))*10
print "Average error is %0.2fms" % error
作为记录,我在我的 HTPC 上得到大约 0.1ms 的错误,在我的笔记本电脑上得到大约 2ms 的错误,两台都是 linux 机器。
如果您需要更精确或更短的睡眠时间,请考虑自己制作:
import time
def sleep(duration, get_now=time.perf_counter):
now = get_now()
end = now + duration
while now < end:
now = get_now()
你不能真正保证关于 sleep() 的任何事情,除非你告诉它它至少会尽最大努力睡觉(信号可以在时间结束之前杀死你的睡眠,还有更多的东西可以让它运行长)。
当然,您可以在标准桌面操作系统上获得的最小值约为 16 毫秒(计时器粒度加上上下文切换时间),但是当您尝试时,与提供的参数的偏差百分比可能会很大睡眠 10 毫秒。
信号、持有 GIL 的其他线程、内核调度乐趣、处理器速度步进等都会对您的线程/进程实际休眠的持续时间造成严重破坏。
def test():
then = time.time() # get time at the moment
x = 0
while time.time() <= then+1: # stop looping after 1 second
x += 1
time.sleep(0.001) # sleep for 1 ms
print(x)
在 Windows 7 / Python 3.81000
上为我返回,即使我将睡眠值设置为0.0005
所以完美的1ms
def start(self):
sec_arg = 10.0
cptr = 0
time_start = time.time()
time_init = time.time()
while True:
cptr += 1
time_start = time.time()
time.sleep(((time_init + (sec_arg * cptr)) - time_start ))
# AND YOUR CODE .......
t00 = threading.Thread(name='thread_request', target=self.send_request, args=([]))
t00.start()
不要使用变量来传递 sleep() 的参数,必须将计算直接插入到 sleep() 中
我的终端机的回归
1 ────── 17:20:16.891 ────────────────────
2 ────── 17:20:18.891 ────────────────────
3 ────── 17:20:20.891 ────────────────────
4 ────── 17:20:22.891 ────────────────────
5 ────── 17:20:24.891 ────────────────────
……
689 ──── 17:43:12.891 ────────────────────
690 ──── 17:43:14.890 ────────────────────
691 ──── 17:43:16.891 ────────────────────
692 ──── 17:43:18.890 ────────────────────
693 ──── 17:43:20.891 ────────────────────
...
727 ──── 17:44:28.891 ────────────────────
728 ──── 17:44:30.891 ────────────────────
729 ──── 17:44:32.891 ────────────────────
730 ──── 17:44:34.890 ────────────────────
731 ──── 17:44:36.891 ────────────────────
time.sleep
在即将发布的 Python (3.11) 中,该方法已被大量重构。现在在 Windows 和 Unix 平台上都可以预期相似的精度,并且默认情况下始终使用最高精度。这是新文档的相关部分:
在 Windows 上,如果 secs 为零,则线程将其时间片的剩余部分交给任何其他准备运行的线程。如果没有其他线程准备好运行,则函数立即返回,线程继续执行。在 Windows 8.1 和更新版本上,实现使用提供 100 纳秒分辨率的高分辨率计时器。如果 secs 为零,则使用 Sleep(0)。
Unix实现:
- 如果可用,使用clock_nanosleep()(分辨率:1 纳秒);
- 或使用 nanosleep() 如果可用(分辨率:1 纳秒);
- 或使用 select() (分辨率:1 微秒)。
因此,在从 python 3.11 开始的大多数平台上,只需调用time.sleep
就可以了,这是一个好消息!做一个类似于@wilbert 的新实现的跨平台基准测试会很好。
最近在 Windows 10 上的 Python 3.7 上对此进行了测试。精度约为 1 毫秒。