1

The code below is in a thread. The code is copied from an answer to a question asked here a couple of years ago (unfortenately I can't find the question at the moment). Though it looks sound to me, I get an error: "ValueError: sleep length must be non-negative". This happens only after about an hour or so. Could it be that it has to do something with the PC going to sleep (I think unlikely, but it's a laptop running Windows 10 ;-)). This is the code:

def upd_variables():
next_call = time.time()
while True:
    measured_temp = 19.5 # te wijzigen in uitlezing van de sensor
    acttemp.configure(text = str(measured_temp))
    humi = '49.5' # te wijzigen in uitlezing van de sensor
    humidity.configure(text = humi)
    actdaytime = datetime.datetime.now()
    today = actdaytime.strftime("%A %d %B %Y     %H:%M:%S")
    datumtijd.configure(text=today)
    if (measured_temp < desired_temp):
        #CV aan
        status.configure(text="CV aan")
    else:
        #CV uit
        status.configure(text="CV uit")
    next_call = next_call+1;
    time.sleep(next_call - time.time())

I hope this is readable, I'm not sure the code block will look like I want it to... BTW: it is part of a thermostat program I'm working on, intended to run on a Raspberry Pi.

jacob
  • 4,656
  • 1
  • 23
  • 32
jozik
  • 31
  • 1
  • 5
  • whats your logic? how many seconds do you want it to sleep? Obviously the next_call was assigned in past as it comes to the line `time.sleep(next_call - time.time())`, which becomes -ve. – uday Jan 25 '16 at 22:45
  • Also please add a tag for what language you're working with on future questions – Andrew Williamson Jan 25 '16 at 22:48
  • @uDay: summarized: next_call = time.time(), next_call = next_call + 1, time.sleep(next_call - time.time(). As in between almost no time is spent, it puzzles me how the value of time.sleep can become negative. It happened again, I'm now almost certain it has something to do with the PC going to sleep. – jozik Jan 25 '16 at 23:41
  • @AndrewWilliamson: Good point, thanks, I will do that. – jozik Jan 25 '16 at 23:42
  • FWIW, I think this was the [old answer](http://stackoverflow.com/a/18180189/2243104). Can you reliably replicate the problem by putting the laptop on sleep? Can you achieve the same thing by stripping the method down by only keeping the `next_call` and `time.time()` calls? Just so we can simplify the question. Does it happen consistently at the same time after sleep? Can you print each `time.time()` call after sleep to see what it returns? – Reti43 Jan 26 '16 at 01:27
  • Unless you're running hard-real-time software on a hard-real-time OS, there are no guarantees about how much time will pass between one instruction and the next. Typically things execute quickly on modern hardware, but there are various things that can occasionally cause them not too, such as the computer being put to sleep, or another (higher priority) task taking over the CPU, or the computer running out of RAM and spending a long time swapping data to/from the hard disk, etc. – Jeremy Friesner Jan 26 '16 at 05:10
  • @Reti43: correct, that is the original question and the answer from Michael Anderson. OK, I stripped the thread to a bare minimum, only a print of time.time(). Ran it, put the PC to sleep, woke it up again and yes, the same message: "ValueError: sleep length must be non-negative". And that is reproducible. So the cause is the PC going to sleep, you're right Jeremy Friesner. Thanks to all of you, I only don't know how to mark the question as solved. – jozik Jan 26 '16 at 13:09
  • You can post your own answer below and check the green mark on its left to mark it as the accepted answer. – Reti43 Jan 26 '16 at 13:13

1 Answers1

1

Well, if it's not clear to everyone.

The problem here is that when your computer sleeps in the middle of the loop, your next_call = next_call+1 gets old, and then you substract time.time() which depending on how much time the computer slept could be a little larger or a lot larger (unless your computer sleeps for less than a second).

next_call = time.time() # Let's assume next_call=1
while True:
    ...
    # computer sleeps for 5 seconds
    next_call = next_call+1 # now next_call=2
    time.sleep(next_call - time.time()) # At this time, time.time() returns 6 (1 start + 5 sleeps) -> 2 - 6 = -4

There are a couple of options to make it behave, the first one and easier would be to add a if that checks that the sleep time is not negative.

Joaquin Sargiotto
  • 1,646
  • 13
  • 12
  • Thanks Joaquin, I sincerely hope I'm not the only one it was not obvious for. I really expected "sleep" to be smart enough not to mess up a running program. – jozik Jan 27 '16 at 13:15