usleep in Python
Question:
I was searching for a usleep() function in Python 2.7.
Does anybody know if it does exist, maybe with another function name?
Answers:
from time import sleep
sleep(seconds)
Since usleep
generally means you want to delay execution for x microseconds, you must divide the seconds value by 1000000.
import time
time.sleep(seconds/1000000.0)
time.sleep()
takes seconds as a parameter.
from time import sleep
sleep(0.1) #sleep during 100ms
import time
usleep = lambda x: time.sleep(x/1000000.0)
usleep(100) #sleep during 100μs
Be very very careful with time.sleep. I got burned by python3 using time.sleep because it is non-monotonic. If the wall clock changes backwards, the time.sleep call won’t finish until the wall clock catches up with where it would have been if the sleep had gone forward as planned. I have not yet found a monotonic blocked sleep for python.
Instead, I recommend Event.wait, like this:
def call_repeatedly(interval, func, *args, **kwargs):
stopped = Event()
def loop():
while not stopped.wait(interval): # the first call is in `interval` secs
try:
func(*args)
except Exception as e:
logger.error(e);
if kwargs.get('exception'):
kwargs.get('exception')(e) # SEND exception to the specified function if there is one.
else:
raise Exception(e)
Thread(target=loop).start()
return stopped.set
how about this:
import time
def usleep(delay):
mdelay = delay /1000
now = time.time()
while now + mdelay > time.time():
pass
An alternate sleep function for python.
Note: Should not be used for multiple threads due to GIL lock, but for multiple subprocesses its fine. Same with time.sleep()
I’m wrapping a C function to Python. I’m using nanosleep() of C library, which halts that thread running for that much amount of time. It is not a busy-wait type of delay which uses much CPU to evaluate some math. The codes are as follows. Put all in a folder, say CWrapper.
C_functions.h
#include <time.h>
int c_sleep_msec(long milliseconds);
int c_sleep_nsec(long nanoseconds);
C_functions.c
#include "C_functions.h"
int c_sleep_msec(long milliseconds) {
struct timespec req;
//struct timespec rem;
if(milliseconds > 999) {
req.tv_sec = (int)(milliseconds / 1000); /* Must be Non-Negative */
req.tv_nsec = (milliseconds - ((long)req.tv_sec * 1000)) * 1000000; /* Must be in range of 0 to 999999999 */
}
else {
req.tv_sec = 0; /* Must be Non-Negative */
req.tv_nsec = milliseconds * 1000000; /* Must be in range of 0 to 999999999 */
}
//rem = NULL;
return nanosleep(&req , NULL);
}
//------------------------------------------------------
int c_sleep_nsec(long nanoseconds) {
struct timespec req;
//struct timespec rem;
if (nanoseconds > 999999999) {
req.tv_sec = (int)(nanoseconds / 1000000000);
req.tv_nsec = (nanoseconds - ((long)req.tv_sec * 1000000000));
}
else {
req.tv_sec = 0;
req.tv_nsec = nanoseconds;
}
//rem = NULL;
return nanosleep(&req , NULL);
}
You can also create a function for micro seconds using the same nanosleep()
CWrapper.pyx
cdef extern from "C_functions.h":
int c_sleep_msec(long milliseconds)
int c_sleep_nsec(long nanoseconds)
def sleep_msec(milliseconds):
return c_sleep_msec(milliseconds)
def sleep_nsec(nanoseconds):
return c_sleep_nsec(nanoseconds)
setup.py
from distutils.core import setup
from distutils.extension import Extension
from Pyrex.Distutils import build_ext
setup(
name = "CWrapper",
ext_modules=[ Extension("CWrapper", ["CWrapper.pyx", "C_functions.c"]) ],
cmdclass = {'build_ext': build_ext}
)
Install python-pyrex. Then run in linux terminal
python setup.py build_ext -i
It will create CWrapper.c, build, and CWrapper.so files. Use CWrapper.so where ever you want, and just import in python.
Note: Compile separately for Raspberry Pi.
Now, test the function
Test_sleep.py
import serial
from multiprocessing import Process
import time
import CWrapper
class TestSleep:
def __init__(self):
self.delay_sec = 0.00000100
self.delay_msec = 30
self.delay_nsec = 1000 #200000000
self.start_time = time.time()
self.process_1 = Process(name="process_1", target=self.process_1_task, args=("process_1",))
self.process_1.daemon = True
self.process_1.start()
self.process_2 = Process(name="process_2", target=self.process_1_task, args=("process_2",))
self.process_2.daemon = True
self.process_2.start()
self.process_3 = Process(name="process_3", target=self.process_1_task, args=("process_3",))
self.process_3.daemon = True
self.process_3.start()
def process_1_task(self, process_name):
start = self.start_time
delay_msec = self.delay_msec
delay_sec = self.delay_sec
delay_nsec = self.delay_nsec
t1 = start
for i in range(1, 81):
status = CWrapper.sleep_msec(delay_msec)
# status = CWrapper.sleep_nsec(delay_nsec)
#status = time.sleep(delay_sec)
t2 = time.time()
elapsed_time = t2 - t1
t1 = t2
print process_name, i, "status:", status, "Elapsed-time:", elapsed_time
if __name__ == '__main__':
test = TestSleep()
# for i in range(1,10000):
# print "main thread", i
# time.sleep(0.1)
while True: # Since daemon=True, main thread should check join() or stay in loop
pass
Vary the parameters delay_sec for time.sleep(), delay_msec for CWrapper.sleep_msec(), delay_nsec for CWrapper.sleep_nsec(). Uncomment the function which you want to test in thread_1_task().
Three lines to call the "original" usleep:
import ctypes
libc = ctypes.CDLL('libc.so.6')
libc.usleep(300000)
tested on centos & alpine both python 3.8.1
I was searching for a usleep() function in Python 2.7.
Does anybody know if it does exist, maybe with another function name?
from time import sleep
sleep(seconds)
Since usleep
generally means you want to delay execution for x microseconds, you must divide the seconds value by 1000000.
import time
time.sleep(seconds/1000000.0)
time.sleep()
takes seconds as a parameter.
from time import sleep
sleep(0.1) #sleep during 100ms
import time
usleep = lambda x: time.sleep(x/1000000.0)
usleep(100) #sleep during 100μs
Be very very careful with time.sleep. I got burned by python3 using time.sleep because it is non-monotonic. If the wall clock changes backwards, the time.sleep call won’t finish until the wall clock catches up with where it would have been if the sleep had gone forward as planned. I have not yet found a monotonic blocked sleep for python.
Instead, I recommend Event.wait, like this:
def call_repeatedly(interval, func, *args, **kwargs):
stopped = Event()
def loop():
while not stopped.wait(interval): # the first call is in `interval` secs
try:
func(*args)
except Exception as e:
logger.error(e);
if kwargs.get('exception'):
kwargs.get('exception')(e) # SEND exception to the specified function if there is one.
else:
raise Exception(e)
Thread(target=loop).start()
return stopped.set
how about this:
import time
def usleep(delay):
mdelay = delay /1000
now = time.time()
while now + mdelay > time.time():
pass
An alternate sleep function for python.
Note: Should not be used for multiple threads due to GIL lock, but for multiple subprocesses its fine. Same with time.sleep()
I’m wrapping a C function to Python. I’m using nanosleep() of C library, which halts that thread running for that much amount of time. It is not a busy-wait type of delay which uses much CPU to evaluate some math. The codes are as follows. Put all in a folder, say CWrapper.
C_functions.h
#include <time.h>
int c_sleep_msec(long milliseconds);
int c_sleep_nsec(long nanoseconds);
C_functions.c
#include "C_functions.h"
int c_sleep_msec(long milliseconds) {
struct timespec req;
//struct timespec rem;
if(milliseconds > 999) {
req.tv_sec = (int)(milliseconds / 1000); /* Must be Non-Negative */
req.tv_nsec = (milliseconds - ((long)req.tv_sec * 1000)) * 1000000; /* Must be in range of 0 to 999999999 */
}
else {
req.tv_sec = 0; /* Must be Non-Negative */
req.tv_nsec = milliseconds * 1000000; /* Must be in range of 0 to 999999999 */
}
//rem = NULL;
return nanosleep(&req , NULL);
}
//------------------------------------------------------
int c_sleep_nsec(long nanoseconds) {
struct timespec req;
//struct timespec rem;
if (nanoseconds > 999999999) {
req.tv_sec = (int)(nanoseconds / 1000000000);
req.tv_nsec = (nanoseconds - ((long)req.tv_sec * 1000000000));
}
else {
req.tv_sec = 0;
req.tv_nsec = nanoseconds;
}
//rem = NULL;
return nanosleep(&req , NULL);
}
You can also create a function for micro seconds using the same nanosleep()
CWrapper.pyx
cdef extern from "C_functions.h":
int c_sleep_msec(long milliseconds)
int c_sleep_nsec(long nanoseconds)
def sleep_msec(milliseconds):
return c_sleep_msec(milliseconds)
def sleep_nsec(nanoseconds):
return c_sleep_nsec(nanoseconds)
setup.py
from distutils.core import setup
from distutils.extension import Extension
from Pyrex.Distutils import build_ext
setup(
name = "CWrapper",
ext_modules=[ Extension("CWrapper", ["CWrapper.pyx", "C_functions.c"]) ],
cmdclass = {'build_ext': build_ext}
)
Install python-pyrex. Then run in linux terminal
python setup.py build_ext -i
It will create CWrapper.c, build, and CWrapper.so files. Use CWrapper.so where ever you want, and just import in python.
Note: Compile separately for Raspberry Pi.
Now, test the function
Test_sleep.py
import serial
from multiprocessing import Process
import time
import CWrapper
class TestSleep:
def __init__(self):
self.delay_sec = 0.00000100
self.delay_msec = 30
self.delay_nsec = 1000 #200000000
self.start_time = time.time()
self.process_1 = Process(name="process_1", target=self.process_1_task, args=("process_1",))
self.process_1.daemon = True
self.process_1.start()
self.process_2 = Process(name="process_2", target=self.process_1_task, args=("process_2",))
self.process_2.daemon = True
self.process_2.start()
self.process_3 = Process(name="process_3", target=self.process_1_task, args=("process_3",))
self.process_3.daemon = True
self.process_3.start()
def process_1_task(self, process_name):
start = self.start_time
delay_msec = self.delay_msec
delay_sec = self.delay_sec
delay_nsec = self.delay_nsec
t1 = start
for i in range(1, 81):
status = CWrapper.sleep_msec(delay_msec)
# status = CWrapper.sleep_nsec(delay_nsec)
#status = time.sleep(delay_sec)
t2 = time.time()
elapsed_time = t2 - t1
t1 = t2
print process_name, i, "status:", status, "Elapsed-time:", elapsed_time
if __name__ == '__main__':
test = TestSleep()
# for i in range(1,10000):
# print "main thread", i
# time.sleep(0.1)
while True: # Since daemon=True, main thread should check join() or stay in loop
pass
Vary the parameters delay_sec for time.sleep(), delay_msec for CWrapper.sleep_msec(), delay_nsec for CWrapper.sleep_nsec(). Uncomment the function which you want to test in thread_1_task().
Three lines to call the "original" usleep:
import ctypes
libc = ctypes.CDLL('libc.so.6')
libc.usleep(300000)
tested on centos & alpine both python 3.8.1