Задержка time.sleep() мягко говоря не соответствует действительности

Вот мой тестовый код

    for i in range(int(steps)):
        start = time.time()
        step.write(1)
        step.write(0)
        time.sleep(0.00001)
        print(time.time()- start)

а вот его результат с задержкой

0.015957355499267578
0.015957355499267578
0.01595783233642578
0.015956640243530273
0.01595759391784668
0.015957355499267578
0.015957117080688477
0.014960289001464844
0.01595759391784668

а вот без задержки

0.000997304916381836
0.000997304916381836
0.000997304916381836
0.000997304916381836
0.000997304916381836
0.000997781753540039
0.0019941329956054688
0.0009975433349609375
0.0009980201721191406

вопрос: какого чёрта и как можно это исправить


Ответы (3 шт):

Автор решения: GrAnd

Вообще считается, что разрешающая способность time.sleep() менее 1ms не гарантируется. Под Windows 7 у меня чётко упирается в это значение:

D:\Programming\Python\1>python -m timeit "time.sleep(1.0/500)"
200 loops, best of 5: 2 msec per loop
D:\Programming\Python\1>python -m timeit "time.sleep(1.0/1000)"
500 loops, best of 5: 1e+03 usec per loop
D:\Programming\Python\1>python -m timeit "time.sleep(1.0/2000)"
200 loops, best of 5: 1e+03 usec per loop
D:\Programming\Python\1>python -m timeit "time.sleep(1.0/5000)"
200 loops, best of 5: 1e+03 usec per loop
D:\Programming\Python\1>python -m timeit "time.sleep(1.0/10000)"
500 loops, best of 5: 1e+03 usec per loop

Под Linux'ом, что оказался под рукой, разрешающая способность выше. Но точность сильно падает при уменьшении задержки ниже 1ms:

tests/_fast_> python -m timeit "time.sleep(1.0/500)"
100 loops, best of 3: 2.1 msec per loop
tests/_fast_> python -m timeit "time.sleep(1.0/1000)"
1000 loops, best of 3: 1.07 msec per loop
tests/_fast_> python -m timeit "time.sleep(1.0/2000)"
1000 loops, best of 3: 559 usec per loop
tests/_fast_> python -m timeit "time.sleep(1.0/5000)"
1000 loops, best of 3: 257 usec per loop
tests/_fast_> python -m timeit "time.sleep(1.0/10000)"
10000 loops, best of 3: 157 usec per loop
tests/_fast_> python -m timeit "time.sleep(1.0/20000)"
10000 loops, best of 3: 107 usec per loop
tests/_fast_> python -m timeit "time.sleep(1.0/50000)"
10000 loops, best of 3: 76.9 usec per loop
tests/_fast_> python -m timeit "time.sleep(1.0/100000)"
10000 loops, best of 3: 66.6 usec per loop
tests/_fast_> python -m timeit "time.sleep(1.0/1000000)"
10000 loops, best of 3: 58 usec per loop

Если я беру ваш код (выкинув всякие step), то мои замеры показывают следующее:

Windows 7:

0.0009999275207519531
0.0010004043579101562
0.0010001659393310547
0.0009999275207519531
0.0009999275207519531
0.0010001659393310547
0.0009999275207519531
0.0010001659393310547
0.0009999275207519531
0.0010001659393310547

Linux:

9.29832458496e-05
7.20024108887e-05
7.20024108887e-05
7.10487365723e-05
7.39097595215e-05
6.41345977783e-05
6.31809234619e-05
6.41345977783e-05
6.41345977783e-05
6.31809234619e-05
→ Ссылка
Автор решения: eri

Я тут почитал про реальное время... лучше 0.000125 точности не получишь на прерываниях таймера.

Самый точный способ - это скушать процессор циклом

a=0

for i in range(int(steps)):
    start = time.time()
    t = time.perf_counter() + 0.00001
    while t > time.perf_counter():
        pass
    a+=time.time()- start

print(a/steps)

Но на вызов time.perf_counter() и time.time() теряется время и на моем компьютере получилось

0.0000110626220703125

вместо 0.00001, ошибка на ~0.000001 не сильно зависит от интервала.

Но в Вашем случае циклы без сна 0.001-0.002 что делает сон в 0.00001 не существенным.

Поищите другой способ задать частоту на выводе - средствами ардуины

→ Ссылка
Автор решения: Александр
from firmata import * 


a = Arduino('COM13')
a.pin_mode(12, firmata.OUTPUT)
a.delay(2)



while True:
    a.digital_write(12, firmata.HIGH)
    a.delay(2)
    a.digital_write(12, firmata.LOW)
    a.delay(2)

Оригинал здесь

Спасибо за поправку @eri

→ Ссылка