快速精确的Python重复计时器 [英] Fast and Precise Python Repeating Timer

查看:69
本文介绍了快速精确的Python重复计时器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要快速,准确地发送列表中的重复消息.一个列表需要每100毫秒发送一次消息,并带有+/- 10毫秒的窗口.我尝试使用下面的代码,但是问题是计时器等待100毫秒,然后需要完成所有计算,使计时器超出了可接受的范围.

I need to send repeating messages from a list quickly and precisely. One list needs to send the messages every 100ms, with a +/- 10ms window. I tried using the code below, but the problem is that the timer waits the 100ms, and then all the computation needs to be done, making the timer fall out of the acceptable window.

仅减少等待时间是一个混乱且不可靠的hack.如果列表在循环中被编辑,则消息循环周围会出现一个锁.

Simply decreasing the wait is a messy, and unreliable hack. The there is a Lock around the message loop in the event the list gets edited during the loop.

关于如何让python在100ms左右一致地发送消息的想法?谢谢

Thoughts on how to get python to send messages consistently around 100ms? Thanks

from threading import Timer
from threading import Lock

class RepeatingTimer(object):
    def __init__(self,interval, function, *args, **kwargs):
        super(RepeatingTimer, self).__init__()
        self.args = args
        self.kwargs = kwargs
        self.function = function
        self.interval = interval
        self.start()

    def start(self):
        self.callback()

    def stop(self):
        self.interval = False

    def callback(self):
        if self.interval:
            self.function(*self.args, **self.kwargs)
            Timer(self.interval, self.callback, ).start()

def loop(messageList):
    listLock.acquire()
    for m in messageList:
        writeFunction(m)
    listLock.release()


MESSAGE_LIST = [] #Imagine this is populated with the messages
listLock = Lock()
rt = RepeatingTimer(0.1,loop,MESSAGE_LIST)
#Do other stuff after this

我确实知道writeFunction会导致一些延迟,但不会超过允许的10毫秒.我基本上需要为每条消息每100毫秒调用一次该函数.消息列表很小,通常少于元素.

I do understand that the writeFunction will cause some delay, but not more than the 10ms allowed. I essentially need to call the function every 100ms for each message. The messagelist is small, usually less than elements.

下一个挑战是每10ms,+/- 1ms:P

The next challenge is to have this work with every 10ms, +/-1ms :P

推荐答案

是的,简单的等待很麻烦,还有更好的选择.

Yes, the simple waiting is messy and there are better alternatives.

首先,您需要使用Python的高精度计时器.有几种选择,根据您的操作系统,您可能希望选择最准确的.

First off, you need a high-precision timer in Python. There are a few alternatives and depending on your OS, you might want to choose the most accurate one.

第二,您必须了解基础抢占式多任务处理并且了解没有高精度sleep函数,并且其实际分辨率也因操作系统而异.例如,如果我们正在使用Windows,则最小睡眠间隔可能约为10-13毫秒.

Second, you must be aware of the basics preemptive multitasking and understand that there is no high-precision sleep function, and that its actual resolution will differ from OS to OS too. For example, if we're talking Windows, the minimal sleep interval might be around 10-13 ms.

第三,请记住,始终可以等待非常精确的时间间隔(假设您具有高分辨率计时器),但是要权衡高CPU负载.该技术称为忙碌等待:

And third, remember that it's always possible to wait for a very accurate interval of time (assuming you have a high-resolution timer), but with a trade-off of high CPU load. The technique is called busy waiting:

while(True):
    if time.clock() == something:
         break

因此,实际的解决方案是创建一个混合计时器.它将使用常规的sleep函数等待间隔的大部分时间,然后在执行sleep(0)技巧时,将开始在循环中探测高精度计时器. Sleep(0)(取决于平台)将等待最短的时间,将其余时间片的其余部分释放给其他进程,并切换CPU上下文.这是相关的讨论.

So, the actual solution is to create a hybrid timer. It will use the regular sleep function to wait the main bulk of the interval, and then it'll start probing the high-precision timer in the loop, while doing the sleep(0) trick. Sleep(0) will (depending on the platform) wait the least possible amount of time, releasing the rest of the remaining time slice to other processes and switching the CPU context. Here is a relevant discussion.

Ryan Geiss的在Win32中计时文章中对此概念进行了详细描述. .它是用C语言编写的,并且用于Windows API,但是基本原理也适用于此.

The idea is thoroughly described in the Ryan Geiss's Timing in Win32 article. It's in C and for Windows API, but the basic principles apply here as well.

这篇关于快速精确的Python重复计时器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆