Skip to content Skip to sidebar Skip to footer

Accurate Sleep/delay Within Python While Loop

I have a while True loop which sends variables to an external function, and then uses the returned values. This send/receive process has a user-configurable frequency, which is sav

Solution 1:

If I understood your question correctly, you want to execute ExternalFunction.main at a given frequency. The problem is that the execution of ExternalFunction.main itself takes some time. If you don't need very fine precision -- it seems that you don't -- my suggestion is doing something like this.

import time

frequency = 1  # Hz
period = 1.0/frequency

while True:
    time_before = time.time()
    [...]
    ExternalFunction.main([...])
    [...]
    while (time.time() - time_before) < period:
        time.sleep(0.001)  # precision here

You may tune the precision to your needs. Greater precision (smaller number) will make the inner while loop execute more often.

This achieves decent results when not using threads. However, when using Python threads, the GIL (Global Interpreter Lock) makes sure only one thread runs at a time. If you have a huge number of threads it may be that it is taking way too much time for the program to go back to your main thread. Increasing the frequency Python changes between threads may give you more accurate delays.

Add this to the beginning of your code to increase the thread switching frequency.

import sys
sys.setcheckinterval(1)

1 is the number of instructions executed on each thread before switching (the default is 100), a larger number improves performance but will increase the threading switching time.

Solution 2:

You may want to try python-pause

Pause until a unix time, with millisecond precision:

import pausepause.until(1370640569.7747359)

Pause using datetime:

import pause, datetimedt= datetime.datetime(2013, 6, 2, 14, 36, 34, 383752)
pause.until(dt)

You may use it like:

freqHz=60.0
td=datetime.timedelta(seconds=1/freqHz)
dt=datetime.now()

whiletrue:
  #Your code here
  dt+=td
  pause.until(dt)

Solution 3:

Another solution for an accurate delay is to use the perf_counter() function from module time. Especially useful in windows as time.sleep is not accurate in milliseconds. See below example where function accurate_delay creates a delay in milliseconds.

import time


defaccurate_delay(delay):
    ''' Function to provide accurate time delay in millisecond
    '''
    _ = time.perf_counter() + delay/1000while time.perf_counter() < _:
        pass


delay = 10
t_start = time.perf_counter()
print('Wait for {:.0f} ms. Start: {:.5f}'.format(delay, t_start))

accurate_delay(delay)

t_end = time.perf_counter()
print('End time: {:.5f}. Delay is {:.5f} ms'.
      format(t_end, 1000*(t_end - t_start)))

sum = 0
ntests = 1000for _ inrange(ntests):
    t_start = time.perf_counter()
    accurate_delay(delay)
    t_end = time.perf_counter()
    print('Test completed: {:.2f}%'.format(_/ntests * 100), end='\r', flush=True)
    sum = sum + 1000*(t_end - t_start) - delay

print('Average difference in time delay is {:.5f} ms.'.format(sum/ntests))`

Post a Comment for "Accurate Sleep/delay Within Python While Loop"