Execute a function periodically in python for every n milliseconds in python 2

11,997

Solution 1

I tried it on my own and it works, but it seems that Python isn't that fast in the console. In my case it just gets to about 60 runs per second.

import threading
import time

def hello(*args):
    print(str(args[0])+" It's "+str(time.ctime()))
    next=int(args[0])+1
    threading.Timer(0.001, hello,[str(next)]).start()

hello("1")

Solution 2

I also had a similar problem in which I needed to do some sampling at 1000Hz and that couldn't have any considerable drift on the long run. Trying to sleep 0.001 seconds would always result in a lower sampling rate (drifting), even when I tried to estimate the time the sampling code took to execute (with a time.time() after and before sleeping).

It turns out that a simple solution is to keep track of the number of executions and use it to calculate if you are late or not.

import time
import threading

class PeriodicSleeper(threading.Thread):
    def __init__(self, task_function, period):
        super().__init__()
        self.task_function = task_function
        self.period = period
        self.i = 0
        self.t0 = time.time()
        self.start()

    def sleep(self):
        self.i += 1
        delta = self.t0 + self.period * self.i - time.time()
        if delta > 0:
            time.sleep(delta)
    
    def run(self):
        while True:
            self.task_function()
            self.sleep()

And for testing:

def task():
    t = time.time()
    if abs(t - round(t)) <= 0.0005:
        print(t, 'Mean Frequency:', sleeper.i / (t - sleeper.t0))

sleeper = PeriodicSleeper(task, 0.001)

Resulting in a deviation that is less than half a period and a mean frequency that converges to the desired value.

1623373581.0000355 Mean Frequency: 999.8594124106243
1623373582.0000308 Mean Frequency: 999.9576212826602
1623373583.0000248 Mean Frequency: 999.9771123402633
1623373584.0000222 Mean Frequency: 999.9844427446347
1623373585.0000298 Mean Frequency: 999.9862123585227
1623373586.000023 Mean Frequency: 999.989990000442
....
1623373863.0000231 Mean Frequency: 999.9998049640523
1623373864.000024 Mean Frequency: 999.9998022878916
1623373865.0000224 Mean Frequency: 999.9998088494829
1623373866.0000248 Mean Frequency: 999.9998011675633
Share:
11,997
surya
Author by

surya

Updated on June 15, 2022

Comments

  • surya
    surya almost 2 years

    I'm wondering how to execute a function in Python for every 10ms. I tried with threading (using threading.Timer(0.001, fun)), but threading.Timer executes properly only up to seconds. Is there any to execute a task/function in ms(milli seconds)?

    The code is as follows.

    def task():
        print "called every 10ms"
        print time.ctime()
        threading.Timer(0.01,task).start()
    
    task()