Python 2.x - Windows 上毫秒级别的 sleep 调用

标签 python windows time sleep clock

我在这个论坛上得到了一些关于如何在 Python 2 中编写时钟对象的很好的提示。我现在已经有了一些可以工作的代码。这是一个以 60 FPS 的速度“滴答”的时钟:

import sys
import time

class Clock(object):

    def __init__(self):

        self.init_os()
        self.fps = 60.0
        self._tick = 1.0 / self.fps
        print "TICK", self._tick
        self.check_min_sleep()
        self.t = self.timestamp()

    def init_os(self):

        if sys.platform == "win32":
            self.timestamp = time.clock
            self.wait = time.sleep

    def timeit(self, f, args):

        t1 = self.timestamp()
        f(*args)
        t2 = self.timestamp()
        return t2 - t1

    def check_min_sleep(self):
        """checks the min sleep time on the system"""

        runs =  1000
        times = [self.timeit(self.wait, (0.001, )) for n in xrange(runs)]
        average = sum(times) / runs
        print "average min sleep time:", round(average, 6)
        sort = sorted(times)
        print "fastest, slowest", sort[0], sort[-1]

    def tick(self):

        next_tick = self.t + self._tick
        t = self.timestamp()
        while t < next_tick:
            t = self.timestamp()
        self.t = t

if __name__ == "__main__":
    clock = Clock()

时钟并没有太糟糕,但为了避免繁忙的循环,我希望 Windows 的 sleep 时间少于通常的大约 15 毫秒。在我的系统(64 位 Windows 10)上,如果 Python 是唯一运行的应用程序,它会在启动时钟时平均返回大约 15/16 毫秒。对于避免繁忙循环的分钟 sleep 来说,这太长了。

有谁知道如何让 Windows sleep 低于该值?

最佳答案

您可以暂时将计时器周期降低到 timeGetDevCaps 返回的 wPeriodMin 值.下面定义了一个调用 timeBeginPeriodtimer_resolution 上下文管理器和 timeEndPeriod功能。

import timeit
import contextlib
import ctypes
from ctypes import wintypes

winmm = ctypes.WinDLL('winmm')

class TIMECAPS(ctypes.Structure):
    _fields_ = (('wPeriodMin', wintypes.UINT),
                ('wPeriodMax', wintypes.UINT))

def _check_time_err(err, func, args):
    if err:
        raise WindowsError('%s error %d' % (func.__name__, err))
    return args

winmm.timeGetDevCaps.errcheck = _check_time_err
winmm.timeBeginPeriod.errcheck = _check_time_err
winmm.timeEndPeriod.errcheck = _check_time_err

@contextlib.contextmanager
def timer_resolution(msecs=0):
    caps = TIMECAPS()
    winmm.timeGetDevCaps(ctypes.byref(caps), ctypes.sizeof(caps))
    msecs = min(max(msecs, caps.wPeriodMin), caps.wPeriodMax)
    winmm.timeBeginPeriod(msecs)
    yield
    winmm.timeEndPeriod(msecs)

def min_sleep():
    setup = 'import time'
    stmt = 'time.sleep(0.001)'
    return timeit.timeit(stmt, setup, number=1000)

例子

>>> min_sleep()
15.6137827

>>> with timer_resolution(msecs=1): min_sleep()
...
1.2827173000000016

with block 之后恢复原始计时器分辨率:

>>> min_sleep()
15.6229814

关于Python 2.x - Windows 上毫秒级别的 sleep 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38487114/

相关文章:

java - 用于程序制作的 Big-O 运行时

windows - 如何使 COM 对象的方法不在主线程中运行

JAVA_HOME 应该指向 JDK 而不是 JRE

python - 无法使用 xpath、lxml 从抓取的页面获取脚本标记的内容

python - 纺车功能并不总是退出

javascript - 为什么我收到此错误 chrome-extension ://invalid

c - 奇怪的时钟()行为

javascript - 解析日期返回null

python - numpy.tensordot 命令如何工作?此命令中对轴求和的含义是什么?

python - tesseract.exe 未安装或不在您的路径中