4

I'd like to create a revenue counter for the sales team at work and would love to use Python. E.g. Joe Bloggs shifts his target from 22.1 to 23.1 (difference of 1.0.) I'd like the counter to tick evenly from 22.1 to 23.1 over an hour.

I've created this script, which works fine for counting a minute (runs 2 seconds over the minute); however, when it's supposed to run for an hour, it runs for 47 minutes.

Question: Does anyone know why it runs faster when I set it to an hour? Is sleep.time inaccurate?

import time

def rev_counter(time_length):
    time_start = (time.strftime("%H:%M:%S"))

    prev_pp = 22.1
    new_pp = 23.1

    difference = new_pp - prev_pp

    iter_difference = (difference / 100000.) # Divide by 100,000 to show 10 decimal places
    time_difference = ((time_length / difference) / 100000.)     

    i = prev_pp

    while i < new_pp:
        print("%.10f" % i)
        i = i + iter_difference
        time.sleep(time_difference)

    time_end = (time.strftime("%H:%M:%S"))

    print "Time started at", time_start
    print "Time ended at", time_end

rev_counter(60) # 60 seconds. Returns 62 seconds
rev_counter(600) # 10 minutes. Returns 10 minutes, 20 secs
rev_counter(3600) # 1 hour. Returns 47 minutes
Sam Perry
  • 2,554
  • 3
  • 28
  • 29
  • related: [Trying to simulate constant byte rate. Confusion with time.sleep results](http://stackoverflow.com/q/26595419/4279) – jfs May 07 '15 at 14:18
  • related: [How to run a function periodically in python](http://stackoverflow.com/a/26609843/4279) – jfs May 07 '15 at 14:21

3 Answers3

2

Please note this quote from the Python documentation for time.sleep()

The actual suspension time may be less than that requested because any caught signal will terminate the sleep() following execution of that signal's catching routine. Also, the suspension time may be longer than requested by an arbitrary amount because of the scheduling of other activity in the system.

As a suggestion, if faced with this problem, I would use a variable to track the time that the interval starts. When sleep wakes up, check to see if the expected time has elapsed. If not, restart a sleep for the difference, etc.

David Hoelzer
  • 15,862
  • 4
  • 48
  • 67
  • Thank you. I'll build the time tracker in. – Sam Perry May 08 '15 at 08:47
  • I'm finding it is taking way too long. E.g. `t0 = time.time(); time.sleep(1); print(time.time() - t0)` consistently takes between 8 to 11 seconds on my machine. Is this a different problem? – Bill Aug 07 '21 at 14:24
  • I see in the documentation for Python 3.9 it now says "Also, the suspension time may be longer than requested by an arbitrary amount because of the scheduling of other activity in the system." – Bill Aug 07 '21 at 18:23
1

First of all, your loop doesn't only contain sleep statements -- the things you do between calling time.sleep take time, too, so if you do 10 repetions, you'll spent only 10% of the time doing these compared to when you have 100 iterations through your loop.

Is sleep.time inaccurate?

Yes. Or well. Quite.

I come from a real-time signal processing background. PC clocks are only somewhat accurate, and the time you spend in your OS, your standard libraries, your scripting language run time and your scripting logic between the point in time when a piece of hardware notifies you that your time has elapsed and the point in time your software notices is significant.

Marcus Müller
  • 34,677
  • 4
  • 53
  • 94
  • one notice, you hardware is not accurate too (but in much lower values) One accurate thing is - atomic clock :) – Reishin May 06 '15 at 12:27
  • @reishin: that's typically what's used to discipline the clocks I'm referring to :) but even those are not really accurate, because that is physically impossible (would require exact knowledge of impulse and time, which can't be done - Heisenberg. " – Marcus Müller May 06 '15 at 21:03
0

I just noticed time.sleep taking way too long (5-30000 times longer for input values between .0001 to 1 second), and searching for an answer, found this thread. I ran some tests and it is consistently doing this (see code and results below). The weird thing is, I restarted, then it was back to normal, working very accurately. When code started to hang it was time.sleep taking 10000 times too long?! So a restart is a temporary solution, but not sure what the cause is/ permanent solution is.

import numpy as np 
import time

def test_sleep(N,w): 
    data = []
    for i in xrange(N): 
        t0 = time.time()
        time.sleep(w)
        t1 = time.time()
        data.append(t1-t0)
    print "ave = %s, min = %s, max = %s" %(np.average(data), np.min(data), np.max(data))
    return data


data1 = test_sleep(20,.0001)
Out: ave = 2.95489487648, min = 1.11787080765, max = 3.23506307602

print data1
Out: [3.1929759979248047,
 3.121081829071045,
 3.1982388496398926,
 3.1221959590911865,
 3.098078966140747,
 3.131525993347168,
 3.12644100189209,
 3.1535091400146484,
 3.2167508602142334,
 3.1277999877929688,
 3.1103289127349854,
 3.125699996948242,
 3.1129801273345947,
 3.1223208904266357,
 3.1313750743865967,
 3.1280829906463623,
 1.117870807647705,
 1.3357980251312256,
 3.235063076019287,
 3.189779043197632]

data2 = test_sleep(20, 1)
Out: ave = 9.44276217222, min = 1.00008392334, max = 10.9998381138

print data2
Out: [10.999573945999146,
 10.999622106552124,
 3.8115758895874023,
 1.0000839233398438,
 3.3502109050750732,
 10.999613046646118,
 10.99983811378479,
 10.999617099761963,
 10.999662160873413,
 10.999619960784912,
 10.999650955200195,
 10.99962306022644,
 10.999721050262451,
 10.999620914459229,
 10.999532222747803,
 10.99965500831604,
 10.999596118927002,
 10.999563932418823,
 10.999600887298584,
 4.6992621421813965]
travelingbones
  • 7,919
  • 6
  • 36
  • 43
  • So restarting and redoing this experiment repeatedly shows that time.sleep() is hanging after the first few minutes of use. That is, it will work accurately for a few minutes, then hang. – travelingbones Jun 17 '16 at 04:53