[Tutor] Accuracy of time.sleep()
Dave S
pythontut at pusspaws.net
Sat Dec 4 22:15:19 CET 2004
Tim Peters wrote:
First, thank you for such a brilliant answer :-)
>[Dave S <pythontut at pusspaws.net>]
>
>
>>OK I may be pushing it, ;-)
>>
>>
>
>Yup <wink>.
>
>
>
>>I need a script to sleep from any point to 8:05AM when in needs to
>>re-start.
>>
>>So I calculate the number of seconds with the following ....
>>
>>def secs_till_805():
>> # Returns the number of seconds till 8:05AM
>>
>> secs_5min=5*60
>> secs_24hr=24*60*60
>> secs_8hr=(8*60*60)+secs_5min
>> secs_8hr_24hr=secs_24hr-secs_8hr
>>
>> hours=int(strftime('%H'))
>> mins=int(strftime('%M'))
>> secs=int(strftime('%S'))
>>
>>
>
>Ouch. Never try to pick apart the current time by computing it more
>than once. For example, if the time at the start of that block is
>just a fraction of a second before 9AM, it's quite possible you'll end
>up with hours==8 and mins==secs==0 (because the time is 8:59:59 at the
>time you do the "%H" business, and but it's 9:00:00 by the time you
>get to "%M"). That would throw you off by an hour. The same kind of
>thing can happen a little before the (any) minute changes too.
>
>
>
This is a possibility that had not enterd my mind, but also very true.
Thanks for saving me from that particular black hole.
Its always that 1 in a thousand possibility that sends things south at
the worst possible moment !
>> sec_left=secs_24hr-((hours*60*60)+(mins*60)+secs)
>>
>> # If we are before 8:05, then ...
>> if sec_left>secs_8hr_24hr:
>> return sec_left-secs_8hr_24hr
>>
>> # If we are after 8:05, then ...
>> return sec_left+secs_8hr
>>
>>
>
>Here's a different way, computing current time only once, and using
>the datetime module to do all the fiddly work:
>
>def seconds_until(h, m=0, s=0):
> from datetime import datetime, time, timedelta
>
> target_time = time(h, m, s)
> now = datetime.now()
> target = datetime.combine(now.date(), target_time)
> if target < now:
> target += timedelta(days=1)
> diff = target - now
> return diff.seconds + diff.microseconds / 1e6
>
>This returns seconds as a float, which is good (Python's time.sleep()
>can make sense of floats, and sleep for fractional seconds).
>
>
>
OK Im pydoc'ing & looking at datetime, a module I have not explored
before. This is stretching me a bit but its a good way to learn.
>>Then I ...
>>
>>sleep(secs_till_805())
>>
>>
>
>With the above, you'd do
>
> time.sleep(seconds_until(8, 5))
>
>instead.
>
>
>
>>I expected the script to re-start 2-3 seconds after 8:05, python
>>reloading after a long sleep etc, what I get is the script restarting at
>>08:04.55, earlier ???
>>
>>
>
>You'll probably never know why for sure. Python calls platform C
>library gimmicks to sleep, which in turn invoke operating system
>facilities. Understanding the whole story would require that you
>understand everything all of those do.
>
>
>
If only I had the time ... (no pun intended)
>[later]
>
>
>>It must be cummulative error over 10s of thousands of seconds.
>>
>>
>
>Maybe.
>
>
>
>>Its a bodge (& cron or at are better) but I suppose I could calculate seconds
>>to 8:05 sleep(seconds*0.95), re calculate secs to 8:05 sleep(seconds)
>>which should reduce the error to almost zip.
>>
>>
>
>That's also a good idea in order to avoid surprises due to crossing
>daylight time boundaries (assuming you mean 8:05 according to the
>local wall clock). Here's a function building on the above:
>
>def sleep_until(h, m=0, s=0):
> from time import sleep
>
> while True:
> delay = seconds_until(h, m, s)
> if delay < 10.0:
> sleep(delay)
> return
> else:
> sleep(delay / 2)
>
>
Thats neat, and more elegent than my hamfisted attempt, I err might
borrow it for my code, on a tempory basis you understand ;-)
sleep_secs=secs_till_805()
log('II','ftsed','Sleeping for '+str(sleep_secs)+' Seconds')
# To compensate for the commulative error over 86,000 secs !
sleep(sleep_secs*0.95)
sleep(secs_till_805())
>That is, it cuts the sleep time in half repeatedly, until less than 10
>seconds remain. It can sleep for hours at a time, but as the target
>time approaches it wakes up more frequently. This should keep the
>program loaded in memory as the target time gets near.
>
>
>
>
Cheers
Dave
More information about the Tutor
mailing list