An Accurate Python Sleep Function
Solution 1:
If you're just looking at the output, buffering might make it appear slightly jittery. You could try to explicitly flush the output, but then you're also at the mercy of whatever is displaying the output. I might even hazard a guess that you're using Jupyter Notebook in your browser, which will also have a bunch of buffering/latency as it updates.
Another issue is that if you expect to be running every 1/3 of a second, is that you will suffer from accumulated errors. It will take a little time to run the loop, print a value (printing will take orders of magnitude more time than the other parts), then start to sleep again. A way to bypass this would be that after you finish doing whatever you want to do (I assume something more interesting than count), compute the time until the next 1/3rd of a second and sleep for that amount of time. Something like:
import random
import time
sleep_until = time.monotonic() + 1/3
for n in range(100):
print(time.monotonic() % 100, n)
time.sleep(random.random() / 4) # some "work"
now = time.monotonic()
if sleep_until > now:
time.sleep(sleep_until - now)
else:
pass
#print('task took too long')
sleep_until += 1/3
For me it gives something like:
48.34696656104643 0
48.68041984003503 1
49.08346292399801 2
49.41925806296058 3
49.72542790300213 4
50.07280854298733 5
50.41882419097237 6
50.74827564903535 7
51.08352101803757 8
51.41813271504361 9
51.75208444998134 10
52.08399672002997 11
52.41870043799281 12
So it bounces around a bit (I'm also running this in Jupyter, which may contribute), but won't stack up error as it runs.
The real question though is what are you trying to do?
Solution 2:
The print
statement in Python takes time to run. If I need a Python program to sleep for a more exact amount of time, I use datetime.timedelta
with a while
loop instead of time.sleep
. Here is my code:
from datetime import datetime, timedelta
startTime = datetime.now()
sleepTime = timedelta(seconds = 5)
# run code here
while startTime+sleepTime > datetime.now():
pass
Also, if you don't mind putting all of your code in funtions you can use a decorator function:
from datetime import datetime, timedelta
def sleep(time):
def outer_wrap(func):
def wrap(*args, **kwargs):
startTime = datetime.now()
sleepTime = timedelta(seconds = time)
while startTime+sleepTime > datetime.now():
pass
func(*args, **kwargs)
return wrap
return outer_wrap
@sleep(5)
def c():
# code goes here
pass
c()
I would reccomend the first method because it can be very inefficient to put all your code in functions.
Note: This will not work if the code you are executing taes longer that the time you are trying to wait. It should work in your case because print
shouldn't take longer than 0.334 seconds.
Solution 3:
OK, this time I have really figured this out. It wasn't IO buffering, nor was it the time it takes to call print() or some spooky OS-specific scheduling voodoo. It was my terminal all along. (...m. night shyamalan twist...) Specifically, xfce4-terminal
, though after trying about seven other terminals, I found lxterminal
has the exact same problem. They're both VTE-based, but there are other VTE-based emulators that don't have the problem, like terminator
and gnome-terminal
. Anyway, I changed terminals, and the problem is fixed.
I bet those of you who weren't using either of the two problematic terminals were wondering what the hell I was talking about.
Post a Comment for "An Accurate Python Sleep Function"