我试着做一个非常简单的节拍器,它以 30 bpm 工作:
While True:
winsound.Beep(1000, 200)
time.sleep(2 - 0.2)
然后,我打开手机上的节拍器应用程序,同时电脑里发出哔哔声,随着时间的推移,它变得不那么精确了。还有另一种方法来做“time.sleep()”吗?甚至是“time.sleep()”内疚吗?
我试着做一个非常简单的节拍器,它以 30 bpm 工作:
While True:
winsound.Beep(1000, 200)
time.sleep(2 - 0.2)
然后,我打开手机上的节拍器应用程序,同时电脑里发出哔哔声,随着时间的推移,它变得不那么精确了。还有另一种方法来做“time.sleep()”吗?甚至是“time.sleep()”内疚吗?
这在多任务操作系统上很难做到:系统很难为您sleep
提供您请求的确切延迟。请参阅python 的 time.sleep() 有多准确?详情。
但是我们可以通过测量时间跨度和调整睡眠延迟来相当接近。Python 3.3+ 提供了time.perf_counter
,它应该非常擅长测量时间间隔,尽管确切的精度取决于您的操作系统和硬件。
这是一个简单的演示,它只打印每个滴答声请求的时间延迟和测量的时间延迟之间的差异。最初的输出有点草率,但它很快就会稳定下来,给出在请求间隔的 10 微秒内的滴答声。但是,播放声音比打印到终端需要更多的系统资源,这可能会影响此技术的精度。为获得最佳结果,请尽量减少计算机上的任务负载,尤其是在它是单核的情况下。
我在这里将延迟设置为 0.2 秒 = 300 bpm。较慢的节拍率可能会降低精度,因为在每个睡眠周期中有更多时间供 CPU 执行其他可能导致睡眠时间比请求长一点的任务。
from time import sleep, perf_counter
delay = d = 0.2
print(60 / delay, 'bpm')
prev = perf_counter()
for i in range(20):
sleep(d)
t = perf_counter()
delta = t - prev - delay
print('{:+.9f}'.format(delta))
d -= delta
prev = t
典型输出
300.0 bpm
+0.000262488
+0.000151862
-0.000019085
-0.000011358
+0.000023078
-0.000015817
-0.000004357
+0.000009283
-0.000012252
+0.000020515
-0.000009061
+0.000003249
-0.000011482
+0.000029230
+0.000001554
-0.000023614
-0.000003286
+0.000000127
-0.000003732
+0.000016311
这些结果来自运行 Linux、YMMV 的旧单核 32 位 2GHz 机器。