python中的精确睡眠时间

python中的精确睡眠时间,python,windows,sleep,Python,Windows,Sleep,我需要在我的一个函数中等待大约25ms。有时,当处理器被其他东西占用时,调用此函数;有时,它将处理器全部放在自己身上 我试过time.sleep(.25),但有时实际上是25ms,有时则需要更长的时间。有没有一种方法可以在不考虑处理器可用性的情况下精确睡眠一段时间 0.25秒是250毫秒,而不是25毫秒。除此之外,在普通操作系统上无法等待25毫秒–您需要一些实时操作系统。因为您使用的是操作系统,所以无法保证您的进程能够在25毫秒内控制CPU 如果你还想试试,最好是有一个繁忙的循环,直到25毫秒过

我需要在我的一个函数中等待大约25ms。有时,当处理器被其他东西占用时,调用此函数;有时,它将处理器全部放在自己身上


我试过
time.sleep(.25)
,但有时实际上是25ms,有时则需要更长的时间。有没有一种方法可以在不考虑处理器可用性的情况下精确睡眠一段时间

0.25秒是250毫秒,而不是25毫秒。除此之外,在普通操作系统上无法等待25毫秒–您需要一些实时操作系统。

因为您使用的是操作系统,所以无法保证您的进程能够在25毫秒内控制CPU

如果你还想试试,最好是有一个繁忙的循环,直到25毫秒过去。类似的方法可能会奏效:

import time
target_time = time.clock() + 0.025
while time.clock() < target_time:
    pass
导入时间
目标时间=时间时钟()+0.025
while time.clock()<目标时间:
通过

您打算做的是一个实时应用程序。Python(可能还有您正在使用的操作系统)并不打算编写此类应用程序,因为时间限制非常严格

为了实现您想要的目标,您需要一个RTOS(实时操作系统),并按照RT最佳实践使用合适的编程语言(通常是C)开发您的应用程序。

来自睡眠方法:

暂停执行给定的秒数。这个论点可能是正确的 表示更精确睡眠时间的浮点数。这个 实际暂停时间可能小于请求的时间,因为 捕获的信号将在执行该命令后终止sleep() 信号捕捉程序。此外,悬挂时间可能更长 由于调度的原因,请求的数量超过了 系统中的其他活动


事实上,这取决于您的底层操作系统。

您使用的是什么系统?如果您使用的是Windows,则可能需要执行以下操作以实现精确计时:

import ctypes
kernel32 = ctypes.windll.kernel32

# This sets the priority of the process to realtime--the same priority as the mouse pointer.
kernel32.SetThreadPriority(kernel32.GetCurrentThread(), 31)
# This creates a timer. This only needs to be done once.
timer = kernel32.CreateWaitableTimerA(ctypes.c_void_p(), True, ctypes.c_void_p())
# The kernel measures in 100 nanosecond intervals, so we must multiply .25 by 10000
delay = ctypes.c_longlong(.25 * 10000)
kernel32.SetWaitableTimer(timer, ctypes.byref(delay), 0, ctypes.c_void_p(), ctypes.c_void_p(), False)
kernel32.WaitForSingleObject(timer, 0xffffffff)

这段代码可以保证你的进程睡眠。25秒。不过要小心——你可能想将优先级降低到2或3,除非绝对重要的是,它会休眠0.25秒。当然,不要将用户终端产品的优先级更改得太高。

编辑:在Windows 10中,这种胡说八道似乎没有必要。试着这样做:

>>> from time import sleep
>>> import timeit
>>> '%.2f%% overhead' % (timeit.timeit('sleep(0.025)', number=100, globals=globals()) / 0.025 - 100)
'0.29% overhead'
.29%左右,是相当低的开销,而且通常非常准确

以前的Windows版本默认情况下的睡眠分辨率为55毫秒,这意味着您的睡眠通话将在25到55毫秒之间。要将睡眠分辨率降至1毫秒,您需要通过调用以下命令设置Windows使用的分辨率:


另一种精确计时和延迟的解决方案是使用模块time中的perf_counter()函数。在windows中特别有用,因为时间。睡眠不是以毫秒为单位的。请参阅下面的示例,其中函数精确_延迟会产生以毫秒为单位的延迟

import time


def accurate_delay(delay):
    ''' Function to provide accurate time delay in millisecond
    '''
    _ = time.perf_counter() + delay/1000
    while time.perf_counter() < _:
        pass


delay = 10
t_start = time.perf_counter()
print('Wait for {:.0f} ms. Start: {:.5f}'.format(delay, t_start))

accurate_delay(delay)

t_end = time.perf_counter()
print('End time: {:.5f}. Delay is {:.5f} ms'.
      format(t_end, 1000*(t_end - t_start)))

sum = 0
ntests = 1000
for _ in range(ntests):
    t_start = time.perf_counter()
    accurate_delay(delay)
    t_end = time.perf_counter()
    print('Test completed: {:.2f}%'.format(_/ntests * 100), end='\r', flush=True)
    sum = sum + 1000*(t_end - t_start) - delay

print('Average difference in time delay is {:.5f} ms.'.format(sum/ntests))
导入时间
def精确_延迟(延迟):
''功能,以毫秒为单位提供准确的时间延迟
'''
_=时间。性能计数器()+延迟/1000
while time.perf_counter()<\u:
通过
延迟=10
t_start=time.perf_计数器()
打印('等待{.0f}毫秒。开始:{.5f}'。格式(延迟,t_开始))
精确延迟(延迟)
t_end=time.perf_计数器()
打印('结束时间:{.5f}。延迟为{.5f}ms'。
格式(t_-end,1000*(t_-end-t_-start)))
总和=0
ntests=1000
对于范围内的(NTEST):
t_start=time.perf_计数器()
精确延迟(延迟)
t_end=time.perf_计数器()
打印('testcompleted:{.2f}%'。格式(u/ntests*100),end='\r',flush=True)
总和=总和+1000*(t_结束-t_开始)-延迟
打印('时间延迟的平均差异为{.5f}ms..格式(总和/NTEST))

不,不是在“大约25毫秒”的非实时系统中<代码>睡眠非常适合完成这项任务。为什么在这里忙着等待会更好?这不取决于分配给每个进程的时间片的长度吗?如果标准时间片为25毫秒,则忙等待肯定会更糟,因为如果活动进程多于内核,这几乎可以保证处理器在等待后不可用。根据我的理解,如果您
time.sleep
等待25毫秒,线程将从活动队列中退出,直到25毫秒过去,之后它将被移动到活动队列中,然后在将来的某个时间执行。如果您忙着等待,您将留在活动队列中。如果您必须每隔0.025秒重复等待并执行某项操作,您可以像这样更新
target\u time+=0.025
,而不是
target\u time=time.clock()+0.025
。这样,您就不会在等待之间“浪费”时间。
import time


def accurate_delay(delay):
    ''' Function to provide accurate time delay in millisecond
    '''
    _ = time.perf_counter() + delay/1000
    while time.perf_counter() < _:
        pass


delay = 10
t_start = time.perf_counter()
print('Wait for {:.0f} ms. Start: {:.5f}'.format(delay, t_start))

accurate_delay(delay)

t_end = time.perf_counter()
print('End time: {:.5f}. Delay is {:.5f} ms'.
      format(t_end, 1000*(t_end - t_start)))

sum = 0
ntests = 1000
for _ in range(ntests):
    t_start = time.perf_counter()
    accurate_delay(delay)
    t_end = time.perf_counter()
    print('Test completed: {:.2f}%'.format(_/ntests * 100), end='\r', flush=True)
    sum = sum + 1000*(t_end - t_start) - delay

print('Average difference in time delay is {:.5f} ms.'.format(sum/ntests))