0

I am trying to create a larger Python script that procures data from external sources and then logs them into a csv file. I have isolated the code I have written for this purpose and it is as follows:

loop_time = time.time()
wait_time = 1
try:
    while True:
        idle_time = (math.ceil((time.time() - loop_time)*1000))
        loop_time= time.time()
        rand1 = math.ceil(random.uniform(0,3))
        rand2 = math.ceil(random.uniform(0,60))
        wait_time_ms = math.ceil(wait_time*1000)
        csvlogger.lvl1([rand1,rand2,idle_time, wait_time_ms])
        execution_time = time.time()-loop_time
        wait_time = 1 - execution_time
        sleep(wait_time)
            
except KeyboardInterrupt:
    print("end of log generation")

My problem is that I need the data logging to occur as close as possible to 1000ms, and one of the data fields in the generated file must include the "idle time", i.e. how long the execution of the loop took place.

When I run the code above I get the following output:

time,Current Output,Voltage Output,Idle Time,Wait Time
15:13:03.314,3,48,0,1000
15:13:04.322,3,59,1009,1000
15:13:05.331,1,36,1009,1000
15:13:06.346,2,8,1015,1000

As you can see, the resulting time is a few miliseconds too large. I do realise it is perhaps nitpicky for most applications, but it is quite important for my purposes. Additionally, I will ultimately have many more things happening in the loop, some of which might actually lead to the execution time larger than 1000ms on certain occasions, so I would appreciate any suggestions for a loop time control that could also account for that.

Zet
  • 1
  • 1
  • "loop time control that could also account for that" meaning it should do what? – matszwecja Apr 19 '23 at 14:29
  • Did you mean to google `"python sleep until time"`? – quamrana Apr 19 '23 at 14:30
  • @matszwecja if the execution of the loop happens to be larger than 1000 ms, it should just let it run till completion and not force it to restart. I know the code I have right now will throw an error if that happens, but this is not something I am concerned with at this very moment, just looking for suggestions on how to tackle this issue – Zet Apr 19 '23 at 14:35
  • 1
    If you need really tight precise timing, I'm afraid using Python might not cut it. – AKX Apr 19 '23 at 14:36

1 Answers1

0

Time measurement in Python depends on the targeted OS, apparently Windows is about 10k times more inaccurate than Linux.

While timer precision is one thing, you mentioned that the expected task duration can exceed 1s of the logging period. If you want to enforce strict 1s logging you should use an async thread for the logger and feed the needed data into it from your worker thread.

Note that interprocess communication results in an additional execution time overhead, see Efficient Python IPC question for potential solutions.

mimak
  • 211
  • 2
  • 9
  • This doesn't really address the problem - time.sleep itself could take a variable time to call, too. – AKX Apr 19 '23 at 15:29
  • Im doubtful about native function call time variance being 'the problem' given 1ms precision and the issues above – mimak Apr 20 '23 at 07:29
  • I'm not – I measured a simple loop that does a variable-length measurement, tries to sleep for exactly the rest of the second, and got sleeps of 0.997 to 1.004 seconds on my Mac. – AKX Apr 20 '23 at 15:34