如何用python以一定的频率触发事件



我想以特定频率激发事件,例如44100hz
我希望下面的代码每秒执行44100次"打印",但事实并非如此。

import time
frequency = 44100
desired_interval = 1 / frequency
events = 0
time_now = time.time()
time_end = time_now +1
while time_now < time_end:
events += 1
print(events)
# some time has passed, sleep for desired interval less passed time
if( desired_interval > ( time.time() - time_now ) ):
time.sleep( desired_interval - ( time.time() - time_now ) )
time_now = time.time()    

这更接近,即使很可能(非常确定(事件"print"不是以常规频率触发的。

import time
frequency = 44100
desired_interval = 1 / frequency
events = 0
time_now = time.time()
time_start = time_now
time_end = time_now +1
while time_now < time_end:
events += 1
print(events)
if( desired_interval * events > ( time.time() - time_start ) ):
# abs mitigate the fact that sometime the result is negative.
time.sleep( abs( desired_interval * events - ( time.time() - time_start ) ) )

time_now = time.time()

要了解为什么事情花费的时间比您想象的要长,我们必须使用探查器

将您的代码保存为timer.py后,我运行了以下操作;

python3 -m cProfile -s tottime timer.py

结果是:

37621
37622
37623
37624
37625
37626
188134 function calls in 1.000 seconds
Ordered by: internal time
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
37626    0.840    0.000    0.840    0.000 {built-in method time.sleep}
37626    0.104    0.000    0.104    0.000 {built-in method builtins.print}
1    0.045    0.045    1.000    1.000 timer.py:1(<module>)
112879    0.012    0.000    0.012    0.000 {built-in method time.time}
1    0.000    0.000    1.000    1.000 {built-in method builtins.exec}
1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

所以,在我的机器上,它每秒运行37626次。大部分时间都花在了运行time.sleep()上。

问题是,在计算延迟时,您没有考虑python代码运行所需的时间。它也没有考虑到Python是在运行其他程序的操作系统之上运行的。

让我们将程序简化为:

import time
frequency = 44100
desired_interval = 1 / frequency * 0.72
events = 0
time_now = time.time()
time_end = time_now + 1
while time_now < time_end:
events += 1
print(events)
time.sleep(desired_interval)
time_now = time.time()

在我的系统上,它每秒打印大约44100次。正如你所看到的,考虑到开销,我不得不将睡眠时间减少约30%。这只是一个玩具程序。

从所需的频率来看,您似乎想要实时进行CD质量的音频处理。老实说,Python可能不是正确的选择。

您应该做的是将想要完成的实际工作封装在一个函数中,并在此函数上运行探查器。评测的结果将告诉您是否可以在所需的时间内完成所需的工作。

如果你做不到,有一些选择可以加快速度;

  • 使用numpy
  • 使用cython
  • 使用pypy

最新更新