2

I'm trying to run a set of code that starts exactly in 5 second blocks from UTC time, starting at an even minute.

For example it would execute each sample at exactly:

11:20:45
11:20:50
11:20:55
11:21:00
11:21:05
11:21:10

I want that to happen regardless of execution time of the code block, if running the code is instant or 3 seconds I still want to execute at the 5 second UTC time intervals.

Not exactly sure how to do this, though I think that datetime.datetime.utcnow().timestamp() - (datetime.datetime.utcnow().timestamp() % 5.0) + 5 gets me the next upcoming start time?

swifty
  • 1,032
  • 12
  • 22

2 Answers2

1

You can use python's scheduler module:

from datetime import datetime
import sched, time

s = sched.scheduler(time.time, time.sleep)

def execute_something(start_time):
    print("starting at: %f" % time.time())
    time.sleep(3)  # simulate a task taking 3 seconds
    print("Done at: %f" % time.time())
    # Schedule next iteration
    next_start_time = start_time + 5
    s.enterabs(next_start_time, 1, execute_something, argument=(next_start_time,))

next_start_time = round(time.time() + 5, -1)  # align to next to 10sec
s.enterabs(next_start_time, 1, execute_something, argument=(next_start_time,))
print("Starting scheduler at: %f" % time.time())
s.run()


# Starting scheduler at: 1522031714.523436

# starting at: 1522031720.005633
# Done at: 1522031723.008825

# starting at: 1522031725.002102
# Done at: 1522031728.005263

# starting at: 1522031730.002157
# Done at: 1522031733.005365

# starting at: 1522031735.002160
# Done at: 1522031738.005370
nicolas
  • 2,440
  • 2
  • 12
  • 16
0

Use time.sleep to wait until the desired time. Note that this is approximate; especially when the system is under high load, your process might not be waken in time. You can increase process priority to increase your chance.

To avoid blocking the waiting thread, run the task in a separate thread, either by constructing a new thread for every task or using a (faster) thread pool, like this:

import concurrent.futures
import time

def do_something():  # Replace this with your real code
    # This code outputs the time and then simulates work between 0 and 10 seconds
    import datetime
    import random
    print(datetime.datetime.utcnow())
    time.sleep(10 * random.random())

pool = concurrent.futures.ThreadPoolExecutor()
while True:
    now = time.time()
    time.sleep(5 - now % 5)
    pool.submit(do_something)
phihag
  • 245,801
  • 63
  • 407
  • 443