Re: [Tutor] Accuracy of time.sleep()

2004-12-04 Thread Tim Peters
[Dave S [EMAIL PROTECTED]]
 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.

sec_left=secs_24hr-((hours*60*60)+(mins*60)+secs)

# If we are before 8:05, then ...
if sec_leftsecs_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).

 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.

[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)

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.
___
Tutor maillist  -  [EMAIL PROTECTED]
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Accuracy of time.sleep()

2004-12-04 Thread Alan Gauld
 It must be cummulative error over 10s of thousands of seconds.

Just so, and depends on howm many other processes are running,
how busy the CPU is etc.

 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.

Thats the approach I suggest in my otther email :-)

Alan G

___
Tutor maillist  -  [EMAIL PROTECTED]
http://mail.python.org/mailman/listinfo/tutor