103

我可以给它浮点数,例如

time.sleep(0.5)

但它有多准确?如果我给它

time.sleep(0.05)

它真的会睡大约 50 毫秒吗?

4

12 回答 12

88

time.sleep 函数的准确性取决于您的底层操作系统的睡眠准确性。对于像普通 Windows 这样的非实时操作系统,您可以休眠的最小时间间隔约为 10-13 毫秒。我在那个时间的几毫秒内看到了准确的睡眠,超过了最小 10-13 毫秒。

更新:就像下面引用的文档中提到的那样,通常在一个循环中进行睡眠,如果它早早唤醒你,它会确保重新进入睡眠状态。

我还应该提到,如果您运行的是 Ubuntu,您可以通过安装 rt 内核包(至少在 Ubuntu 10.04 LTS 中)来试用伪实时内核(带有 RT_PREEMPT 补丁集)。

编辑:更正非实时 Linux 内核的最小睡眠间隔更接近 1 毫秒然后 10 毫秒,但它以不确定的方式变化。

于 2009-07-15T20:38:44.463 回答
63

人们对操作系统和内核之间的差异是完全正确的,但是我在 Ubuntu 中没有看到任何粒度,而在 MS7 中我看到了 1 毫秒的粒度。建议 time.sleep 的不同实现,而不仅仅是不同的滴答率。顺便说一下,仔细检查表明 Ubuntu 中的粒度为 1μs,但这是由于我用于测量准确性的 time.time 函数。 Python 中 Linux 和 Windows 的典型 time.sleep 行为

于 2013-04-12T09:23:01.843 回答
28

文档中:

另一方面, time()and的精度sleep()优于它们的 Unix 等效项:时间以浮点数表示, time()返回可用的最准确时间(gettimeofday 在可用的情况下使用 Unix),并且sleep()将接受具有非零分数的时间(select使用Unix实现这一点,如果有的话)。

具体地说:_sleep()

在给定的秒数内暂停执行。该参数可以是一个浮点数,以指示更精确的睡眠时间。实际的挂起时间可能少于请求的时间,因为任何捕获的信号都将终止该sleep()信号的捕获例程的后续执行。此外,由于系统中其他活动的调度,暂停时间可能比请求的时间长任意量。

于 2009-07-15T20:37:01.333 回答
28

这是我对威尔伯特回答的后续行动:Mac OS X Yosemite 也是如此,因为它还没有被太多提及。Mac OS X Yosemite 的睡眠行为

看起来很多时候它的睡眠时间大约是您请求时间的 1.25 倍,有时睡眠时间是您请求时间的 1 到 1.25 倍。它几乎从不(大约 1000 个样本中的两次)睡眠时间显着超过您请求时间的 1.25 倍。

此外(未明确显示)1.25 关系似乎保持得很好,直到您低于大约 0.2 毫秒,之后它开始变得有点模糊。此外,在请求的时间量超过 20 毫秒后,实际时间似乎比您请求的长约 5 毫秒。

同样,它在 OS X 中的实现似乎与sleep()在 Windows 或任何 Linux 内核 Wilbert 使用的完全不同。

于 2015-06-05T17:25:35.653 回答
17

为什么不知道:

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 机器。

于 2009-07-15T20:52:09.290 回答
10

如果您需要更精确或更短的睡眠时间,请考虑自己制作:

import time

def sleep(duration, get_now=time.perf_counter):
    now = get_now()
    end = now + duration
    while now < end:
        now = get_now()
于 2020-02-12T10:13:35.617 回答
5

一个小修正,有几个人提到可以通过一个信号提前结束睡眠。在3.6 文档中它说,

在 3.5 版更改:即使睡眠被信号中断,该函数现在至少睡眠几秒钟,除非信号处理程序引发异常(有关基本原理,请参阅PEP 475)。

于 2018-04-25T15:04:14.297 回答
3

你不能真正保证关于 sleep() 的任何事情,除非你告诉它它至少会尽最大努力睡觉(信号可以在时间结束之前杀死你的睡眠,还有更多的东西可以让它运行长)。

当然,您可以在标准桌面操作系统上获得的最小值约为 16 毫秒(计时器粒度加上上下文切换时间),但是当您尝试时,与提供的参数的偏差百分比可能会很大睡眠 10 毫秒。

信号、持有 GIL 的其他线程、内核调度乐趣、处理器速度步进等都会对您的线程/进程实际休眠的持续时间造成严重破坏。

于 2009-07-15T20:45:43.373 回答
1
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

于 2020-10-25T02:11:46.303 回答
0
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 ────────────────────

于 2019-01-12T16:52:25.453 回答
0

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 的新实现的跨平台基准测试会很好。

于 2022-02-22T08:46:35.013 回答
0

最近在 Windows 10 上的 Python 3.7 上对此进行了测试。精度约为 1 毫秒。

于 2018-07-31T20:02:16.030 回答