【发布时间】:2018-08-05 16:10:19
【问题描述】:
首先,我是 Python 新手,不熟悉它的功能。我一直主要使用MATLAB。
PC 简要规格:Windows 10、Intel i7
我正在尝试制作一个计时器类,用于定期执行诸如 MATLAB 具有的函数,这显然是从 Java 计时器借来的。 MATLAB 计时器的分辨率约为 1 毫秒,我从未见过它在任何情况下都超过 2 毫秒。其实对于我的项目来说已经足够准确了。
最近,由于 MATLAB 的并行计算和 Web 访问功能较差,我计划转向 Python。然而,不幸的是,与我必须制作自己的定时器类的 MATLAB 相比,Python 的标准包提供了一些低级别的定时器(threading.Timer)。首先,我提到了 QnA Executing periodic actions in Python [duplicate]。 Michael Anderson 建议的解决方案给出了漂移校正的简单概念。他使用 time.sleep() 来保持期间。该方法非常准确,有时比 MATLAB 计时器显示出更好的准确性。大约0.5 毫秒分辨率。但是,定时器在 time.sleep() 中被捕获期间不能被中断(暂停或恢复)。但我有时不得不立即停止,不管它是否处于 sleep() 中。
我发现的问题的解决方案是利用线程包中的 Event 类。请参阅Python threading.timer - repeat function every 'n' seconds 。使用 Event.wait() 的超时功能,我可以在执行之间设置一个时间间隔,它用于保持时间段。也就是说,事件通常会被清除,因此 wait(timeout) 可以像 time.sleep(interval) 一样起作用,并且我可以在需要时通过设置事件立即退出 wait()。
当时一切似乎都很好,但 Event.wait() 中存在一个严重问题。时间延迟在 1 ~ 15 ms 之间变化太大。我认为它来自 Event.wait() 的开销。
我做了一个示例代码,显示 time.sleep() 和 Event.wait() 之间的准确性比较。这总计 1 毫秒 sleep() 和 wait() 的 1000 次迭代,以查看累积的时间误差。预期结果约为 1.000。
import time
from threading import Event
time.sleep(3) # to relax
# time.sleep()
tspan = 1
N = 1000
t1 = time.perf_counter()
for _ in range(N):
time.sleep(tspan/N)
t2 = time.perf_counter()
print(t2-t1)
time.sleep(3) # to relax
# Event.wait()
tspan = 1
event = Event()
t1 = time.perf_counter()
for _ in range(N):
event.wait(tspan/N)
t2 = time.perf_counter()
print(t2-t1)
结果:
1.1379848184879964
15.614547161211096
结果表明 time.sleep() 的准确性要好得多。但我不能像前面提到的那样纯粹依赖 time.sleep()。
总之,
- time.sleep():准确但不可中断
- threading.Event.wait():不准确但可中断
我目前正在考虑妥协:就像在示例中一样,创建一个微小的 time.sleep() 循环(间隔为 0.5 毫秒)并使用 if 语句和 break 退出循环需要的时候。据我所知,该方法用于Python 2.x Python time.sleep() vs event.wait()。
这是一个冗长的介绍,但我的问题可以总结如下。
我能否通过外部信号或事件强制线程进程从 time.sleep() 中断? (这似乎是最有效的。???)
使 Event.wait() 更准确或减少开销时间。
除了 sleep() 和 Event.wait() 方法之外,还有没有更好的方法来提高计时精度。
非常感谢。
【问题讨论】:
标签: python multithreading timer sleep periodic-task