Mogę mu podać liczby zmiennoprzecinkowe, takie jak
time.sleep(0.5)
ale jak dokładne jest to? Jeśli to dam
time.sleep(0.05)
czy to naprawdę będzie spać około 50 ms?
Odpowiedzi:
Dokładność funkcji time.sleep zależy od dokładności uśpienia systemu operacyjnego. W przypadku systemów operacyjnych nie działających w czasie rzeczywistym, takich jak standardowy system Windows, najmniejszy odstęp czasu, w którym można spać, wynosi około 10-13 ms. Widziałem dokładne uśpienia w ciągu kilku milisekund od tego czasu, gdy powyżej minimum 10-13 ms.
Aktualizacja: Jak wspomniano w przytoczonych poniżej dokumentach, często spać w pętli, która zapewni powrót do snu, jeśli obudzi Cię wcześnie.
Powinienem również wspomnieć, że jeśli używasz Ubuntu, możesz wypróbować jądro pseudo czasu rzeczywistego (z zestawem poprawek RT_PREEMPT), instalując pakiet jądra rt (przynajmniej w Ubuntu 10.04 LTS).
EDYCJA: Korekcja jądra Linuksa nie działającego w czasie rzeczywistym ma minimalny interwał uśpienia znacznie bliższy 1 ms niż 10 ms, ale zmienia się w sposób niedeterministyczny.
sleep()
z dokumentacji „czas zawieszenia może być dłuższy niż żądany przez dowolną kwotę z powodu harmonogramu inna aktywność w systemie ”.
Ludzie mają rację co do różnic między systemami operacyjnymi i jądrem, ale nie widzę żadnej szczegółowości w Ubuntu, a widzę ziarnistość 1 ms w MS7. Sugerowanie innej implementacji time.sleep, a nie tylko innej częstotliwości taktowania. Bliższa inspekcja sugeruje przy okazji ziarnistość 1μs w Ubuntu, ale wynika to z funkcji time.time, której używam do pomiaru dokładności.
Z dokumentacji :
Z drugiej strony, precyzja
time()
isleep()
jest lepiej niż ich odpowiedniki Unix: czasy są wyrażone w liczbach zmiennoprzecinkowych,time()
zwraca najbardziej dokładny czas dostępne (za pomocą Unixgettimeofday
, gdzie jest dostępny) isleep()
zaakceptuje razem z frakcją niezerową (Unixselect
jest używany do wdrożenia tego, jeśli jest to możliwe).
A dokładniej wrt sleep()
:
Wstrzymaj wykonywanie na podaną liczbę sekund. Argumentem może być liczba zmiennoprzecinkowa wskazująca dokładniejszy czas uśpienia. Rzeczywisty czas zawieszenia może być krótszy niż żądany, ponieważ każdy przechwycony sygnał zakończy
sleep()
kolejne wykonanie procedury przechwytywania tego sygnału. Ponadto czas zawieszenia może być dłuższy niż żądany przez dowolną kwotę ze względu na harmonogram innych działań w systemie.
Oto moja kontynuacja odpowiedzi Wilberta: to samo dla Mac OS X Yosemite, ponieważ nie zostało jeszcze dużo wspominane.
Wygląda na to, że przez większość czasu przesypia około 1,25 razy dłużej niż prosisz, a czasami przesypia od 1 do 1,25 razy dłużej niż prosisz. Prawie nigdy (~ dwa razy na 1000 próbek) śpi znacznie dłużej niż 1,25 razy dłużej niż żądasz.
Również (nie pokazane bezpośrednio) zależność 1,25 wydaje się utrzymywać całkiem dobrze, dopóki nie spadnie poniżej około 0,2 ms, po czym zaczyna się trochę rozmywać. Ponadto wydaje się, że rzeczywisty czas ustala się o około 5 ms dłużej niż żądasz, gdy żądany czas przekroczy 20 ms.
Ponownie wydaje się, że jest to zupełnie inna implementacja sleep()
w systemie OS X niż w systemie Windows lub jakimkolwiek jądrze Linuksa, którego używał Wilbert.
Dlaczego się nie dowiesz:
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
Dla przypomnienia, pojawia się błąd około 0,1 ms na moim HTPC i 2 ms na moim laptopie, na obu komputerach z systemem Linux.
Mała korekta, kilka osób wspomina, że sen można zakończyć wcześnie sygnałem. W dokumentach 3.6 mówi:
Zmieniono w wersji 3.5: Funkcja zasypia teraz co najmniej sekund, nawet jeśli uśpienie jest przerywane przez sygnał, chyba że program obsługi sygnału zgłosi wyjątek ( uzasadnienie w PEP 475 ).
Naprawdę nie możesz zagwarantować niczego związanego ze snem (), z wyjątkiem tego, że przynajmniej postara się zasnąć tak długo, jak to powiedziałeś (sygnały mogą zabić twój sen, zanim upłynie czas, a wiele innych rzeczy może sprawić, że będzie działał długie).
Na pewno minimum, które możesz uzyskać w standardowym systemie operacyjnym dla komputerów stacjonarnych, będzie wynosić około 16 ms (szczegółowość timera plus czas do przełączenia kontekstu), ale są szanse, że odchylenie% od podanego argumentu będzie znaczące, gdy próbujesz spać przez 10 milisekund.
Sygnały, inne wątki przechowujące GIL, zabawa z planowaniem jądra, stopniowanie szybkości procesora itp. Mogą siać spustoszenie w czasie, w którym wątek / proces faktycznie śpi.
Testowałem to niedawno w Pythonie 3.7 w systemie Windows 10. Precyzja wynosiła około 1 ms.
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()
Nie używaj zmiennej do przekazywania argumentu sleep (), musisz wstawić obliczenie bezpośrednio do funkcji sleep ()
I zwrot mojego terminala
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 ────────────────────
def test():
then = time.time() # get time at the moment
x = 0
while time.time() <= then+1: # stop looping after 1 second
x += 1
time.sleep(0.001) # sleep for 1 ms
print(x)
W 1000
systemie Windows 7 / Python 3.8 zwrócił mi się, nawet jeśli ustawię wartość uśpienia na0.0005
więc idealny 1 ms