Respostas:
A precisão da função time.sleep depende da precisão do sono do seu sistema operacional. Para sistemas operacionais não em tempo real, como um Windows padrão, o menor intervalo pelo qual você pode dormir é de cerca de 10-13 ms. Tenho visto dormidas precisas em vários milissegundos desse tempo, quando acima do mínimo de 10-13 ms.
Atualização: Como mencionado nos documentos citados abaixo, é comum fazer o sleep in the loop que fará com que você volte a dormir caso acorde cedo.
Devo também mencionar que se você estiver executando o Ubuntu, pode experimentar um kernel pseudo-tempo real (com o conjunto de patches RT_PREEMPT) instalando o pacote do kernel rt (pelo menos no Ubuntu 10.04 LTS).
EDIT: Kernels de correção não em tempo real do Linux têm intervalo mínimo de hibernação muito mais próximo de 1 ms do que 10 ms, mas varia de maneira não determinística.
sleep()
dos documentos "o tempo de suspensão pode ser mais longo do que o solicitado por uma quantidade arbitrária por causa da programação de outra atividade no sistema ".
As pessoas estão certas sobre as diferenças entre sistemas operacionais e kernels, mas não vejo nenhuma granularidade no Ubuntu e vejo uma granularidade de 1 ms no MS7. Sugerindo uma implementação diferente de time.sleep, não apenas uma taxa de tick diferente. A propósito, uma inspeção mais detalhada sugere uma granularidade de 1μs no Ubuntu, mas isso se deve à função time.time que uso para medir a precisão.
Da documentação :
Por outro lado, a precisão de
time()
esleep()
é melhor do que seus equivalentes Unix: os tempos são expressos como números de ponto flutuante,time()
retorna o tempo mais preciso disponível (usando Unixgettimeofday
quando disponível) esleep()
aceitará um tempo com uma fração diferente de zero (Unixselect
é usado para implementar isso, quando disponível).
E mais especificamente wrt sleep()
:
Suspenda a execução por um determinado número de segundos. O argumento pode ser um número de ponto flutuante para indicar um tempo de sono mais preciso. O tempo de suspensão real pode ser menor do que o solicitado porque qualquer sinal capturado encerrará a
sleep()
execução seguinte da rotina de captura desse sinal. Além disso, o tempo de suspensão pode ser maior do que o solicitado por um valor arbitrário devido ao agendamento de outra atividade no sistema.
Aqui está o meu acompanhamento à resposta de Wilbert: o mesmo para Mac OS X Yosemite, já que ainda não foi muito mencionado.
Parece que muitas vezes ele dorme cerca de 1,25 vezes o tempo que você solicitou e às vezes dorme entre 1 e 1,25 vezes o tempo que você solicitou. Quase nunca (~ duas vezes em 1000 amostras) dorme significativamente mais do que 1,25 vezes o tempo que você solicitar.
Além disso (não mostrado explicitamente), o relacionamento de 1,25 parece se manter muito bem até você ficar abaixo de cerca de 0,2 ms, após o qual começa a ficar um pouco confuso. Além disso, o tempo real parece se estabilizar em cerca de 5 ms a mais do que o solicitado depois que a quantidade de tempo solicitada ficar acima de 20 ms.
Novamente, parece ser uma implementação completamente diferente sleep()
no OS X do que no Windows ou qualquer outro kernel do Linux que Wilbert estava usando.
Por que você não descobre:
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
Para o registro, eu obtenho cerca de 0,1ms de erro no meu HTPC e 2ms no meu laptop, ambas as máquinas Linux.
Uma pequena correção, várias pessoas mencionam que o sono pode ser interrompido mais cedo por um sinal. Nos documentos 3.6 , diz:
Alterado na versão 3.5: A função agora dorme pelo menos segundos, mesmo se o sono for interrompido por um sinal, exceto se o manipulador de sinal levantar uma exceção (consulte PEP 475 para a justificativa).
Você realmente não pode garantir nada sobre o sono (), exceto que ele fará pelo menos um esforço para dormir, desde que você diga (sinais podem matar seu sono antes que o tempo acabe, e muitas outras coisas podem fazê-lo funcionar longo).
Com certeza, o mínimo que você pode obter em um sistema operacional de desktop padrão será em torno de 16 ms (granularidade do cronômetro mais tempo para alternar o contexto), mas as chances são de que a% de desvio do argumento fornecido será significativo quando você tentar dormir por 10 segundos de milissegundos.
Sinais, outros threads que prendem o GIL, agendamento de kernel divertido, aumento da velocidade do processador, etc. podem causar estragos na duração do seu thread / processo realmente adormecido.
Testei isso recentemente em Python 3.7 no Windows 10. A precisão era de cerca de 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()
Não use uma variável para passar o argumento de sleep (), você deve inserir o cálculo diretamente em sleep ()
E o retorno do meu terminal
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 ───────────────────────