Я можу дати йому числа з плаваючою комою, наприклад
time.sleep(0.5)
але наскільки це точно? Якщо я дам це
time.sleep(0.05)
чи справді він буде спати близько 50 мс?
Відповіді:
Точність функції time.sleep залежить від точності сну вашої базової ОС. Для ОС, що не працюють в режимі реального часу, як звичайна Windows, найменший інтервал, протягом якого ви можете спати, становить близько 10-13 мс. Я бачив точний сон протягом декількох мілісекунд того часу, коли він перевищував мінімум 10-13 мс.
Оновлення: Як згадувалося в цитованих нижче документах, звичайно робити сон у циклі, який обов’язково повернеться спати, якщо він рано вас прокине.
Слід також зазначити, що якщо ви використовуєте Ubuntu, ви можете спробувати псевдо ядро в режимі реального часу (із встановленим патчем RT_PREEMPT), встановивши пакет ядра rt (принаймні в Ubuntu 10.04 LTS).
РЕДАГУВАТИ: Ядра Linux для корекції не в реальному часі мають мінімальний інтервал сну набагато ближчий до 1 мс, ніж 10 мс, але він змінюється недетермінованим чином.
sleep()
із документів. "Час призупинення може бути довшим, ніж вимагається довільною сумою через планування інша діяльність у системі ".
Люди цілком мають рацію щодо відмінностей між операційними системами та ядрами, але я не бачу деталізації в Ubuntu, а в MS7 я бачу деталізацію в 1 мс. Запропонуйте іншу реалізацію time.sleep, а не просто різну частоту галочок. Більш пильний огляд припускає, що в Ubuntu деталізація дорівнює 1 мкс, але це пов’язано з функцією time.time, яку я використовую для вимірювання точності.
З документації :
З іншого боку, точність
time()
таsleep()
краща за їхні еквіваленти Unix: рази виражаються як числа з плаваючою комою,time()
повертає найбільш точний доступний час (з використанням Unix,gettimeofday
де це можливо) іsleep()
приймає час з ненульовою часткою (select
використовується Unix для реалізації цього, де це можливо).
А точніше wrt sleep()
:
Призупиніть виконання на задану кількість секунд. Аргументом може бути число з плаваючою комою для позначення більш точного часу сну. Фактичний час призупинення може бути меншим, ніж запитуваний, оскільки будь-який зловлений сигнал припиняє
sleep()
наступне виконання процедури лову цього сигналу. Крім того, час призупинення може бути довшим, ніж вимагається на довільну суму, через планування інших дій у системі.
Ось моя подальша відповідь на відповідь Вілберта: те саме для Mac OS X Yosemite, оскільки про неї ще мало згадували.
Схоже, багато часу він спить приблизно в 1,25 рази від часу, який ви просите, а іноді перебуває від 1 до 1,25 разів за час, який ви запитуєте. Він майже ніколи (~ двічі з 1000 зразків) не спить значно більше, ніж в 1,25 рази за час, який ви вимагаєте.
Також (не показано чітко) відносини 1,25, здається, тримаються досить добре, поки ви не опуститесь приблизно 0,2 мс, після чого починає трохи розмиватися. Крім того, фактичний час здається приблизно на 5 мс довше, ніж ви вимагаєте, після того, як кількість запитуваного часу перевищить 20 мс.
Знову ж таки, схоже, це зовсім інша реалізація sleep()
в OS X, ніж в Windows, або в залежності від того, яке ядро Linux використовував Вільберт.
Чому б вам не дізнатися:
from datetime import datetime
import time
def check_sleep(amount):
start = datetime.now()
time.sleep(amount)
end = datetime.now()
delta = end-start
return delta.seconds + delta.microseconds/1000000.
error = sum(abs(check_sleep(0.050)-0.050) for i in xrange(100))*10
print "Average error is %0.2fms" % error
Для протоколу я отримую помилку 0,1 мс на моєму HTPC і 2 мс на ноутбуці, обидві машини Linux.
Невелика корекція, кілька людей згадують, що сон можна закінчити рано сигналом. У 3,6 документації сказано:
Змінено у версії 3.5: функція тепер працює щонайменше секунд, навіть якщо режим сну переривається сигналом, за винятком випадків, коли обробник сигналу викликає виняток (див. Обґрунтування PEP 475 ).
Ви насправді не можете нічого гарантувати щодо сну (), за винятком того, що він, принаймні, докладе максимум зусиль, щоб заснути до тих пір, поки ви йому це сказали (сигнали можуть убити ваш сон до закінчення часу, і багато іншого може зробити його запущеним довго).
Звичайно, мінімум, який ви можете отримати в стандартній операційній системі для настільних ПК, складатиме близько 16 мс (деталізація таймера плюс час до перемикання контексту), але є ймовірність того, що% відхилення від наданого аргументу буде значним при спробі спати 10 секунд мілісекунд.
Сигнали, інші потоки, що утримують GIL, задоволення від планування ядра, швидкість процесора тощо тощо можуть зіпсувати хаос із часом, коли ваш потік / процес насправді спить.
Нещодавно тестували це на Python 3.7 у Windows 10. Точність становила близько 1 мс.
def start(self):
sec_arg = 10.0
cptr = 0
time_start = time.time()
time_init = time.time()
while True:
cptr += 1
time_start = time.time()
time.sleep(((time_init + (sec_arg * cptr)) - time_start ))
# AND YOUR CODE .......
t00 = threading.Thread(name='thread_request', target=self.send_request, args=([]))
t00.start()
Не використовуйте змінну для передачі аргументу sleep (), ви повинні вставити обчислення безпосередньо в sleep ()
І повернення мого терміналу
1 ───── 17: 20: 16.891 ───────────────────
2 ───── 17: 20: 18.891 ───────────────────
3 ───── 17: 20: 20.891 ───────────────────
4 ───── 17: 20: 22.891 ───────────────────
5 ───── 17: 20: 24.891 ───────────────────
....
689 ─── 17: 43: 12.891 ────────────────────
690 ─── 17: 43: 14.890 ────────────────────
691 ─── 17: 43: 16.891 ────────────────────
692 ─── 17: 43: 18.890 ────────────────────
693 ─── 17: 43: 20.891 ────────────────────
...
727 ─── 17: 44: 28,891 ────────────────────
728 ─── 17: 44: 30,891 ────────────────────
729 ─── 17: 44: 32,891 ────────────────────
730 ─── 17: 44: 34.890 ────────────────────
731 ─── 17: 44: 36,891 ────────────────────