user3080600
user3080600

Reputation: 1359

Run a function at the start of every round 5 minute interval

I want to run a function every 5 minutes, it must be at a "round" intervals, for example :

12:05:00, 12:10:00, 12:15:00...

It cannot be like this:

12:06:00, 12:11:00, 12:16:00...

Or like this:

12:05:14, 12:10:14, 12:15:14...

What is the most accurate way to do this in python?

Upvotes: 2

Views: 3038

Answers (4)

antonioACR1
antonioACR1

Reputation: 1383

I'm adding this answer because it might be useful for someone else (at least it's what I was looking for...).

In case you want to use schedule then you could combine .hour with several at's (00:00, 05:00, 10:00, etc) as follows:

import schedule
import time
from datetime import datetime

def job():
    print(datetime.now())

schedule.every().hour.at('00:00').do(job)
schedule.every().hour.at('05:00').do(job)
schedule.every().hour.at('10:00').do(job)
schedule.every().hour.at('15:00').do(job)
schedule.every().hour.at('20:00').do(job)
schedule.every().hour.at('25:00').do(job)
schedule.every().hour.at('30:00').do(job)
schedule.every().hour.at('35:00').do(job)
schedule.every().hour.at('40:00').do(job)
schedule.every().hour.at('45:00').do(job)
schedule.every().hour.at('50:00').do(job)
schedule.every().hour.at('55:00').do(job)

while True:
    schedule.run_pending()
    time.sleep(0.1)

Output:

2024-07-29 15:25:00.055969
2024-07-29 15:30:00.040277
2024-07-29 15:35:00.062242
2024-07-29 15:40:00.009916
2024-07-29 15:45:00.078516
2024-07-29 15:50:00.025548
2024-07-29 15:55:00.048082
2024-07-29 16:00:00.032947
2024-07-29 16:05:00.079079
2024-07-29 16:10:00.014529
2024-07-29 16:15:00.097382
2024-07-29 16:20:00.029270
2024-07-29 16:25:00.082946

Upvotes: 0

bigh_29
bigh_29

Reputation: 2643

You could use a threading.Timer. You have to do some math to calculate the next run time. datetime has a handy replace method for that.

from datetime import datetime, timedelta
from threading import Timer
from time import sleep
import random

def schedule_next_run():
    sleep_time = get_sleep_time()
    t = Timer(sleep_time, do_work)
    t.daemon = True
    t.start()
    print(f'sleeping for {sleep_time} seconds')

def get_sleep_time():
    now = datetime.now()
    last_run_time = now.replace(minute=now.minute // 5 * 5, second=0, microsecond=0)
    next_run_time = last_run_time + timedelta(minutes=5)
    return (next_run_time - now).total_seconds()

def do_work():
    now = datetime.now()
    print('Doing some work at', now)
    sleep(random.uniform(0, 29))
    print('Work complete. Scheduling next run.')
    schedule_next_run()

print('Starting work schedule')
schedule_next_run()
input('Doing work every 5 minutes. Press enter to exit:\n')

On my system, the function fires within a half millisecond of the target time

Note that the time calculation rounds down and then adds a timedelta to carefully wrap around the end of each hour. You would want to ponder how this will behave around daylight savings changes.

Suggestion: move all this logic to a class to clean it up.

Upvotes: 4

Ashish Sharma
Ashish Sharma

Reputation: 58

import datetime, time

def some_function():

ran_once = True

while True:
    current_time = datetime.datetime.now()
    if  current_time.minute % 5 == 0 and current_time.second % 60 == 0 and not ran_once:
        print(current_time) # DO YOUR WORK HERE
        ran_once = True

    elif current_time.minute % 5 == 0 or current_time.second % 60 != 0:

        if current_time.second % 60 == 0:
            print("Time to wait:", 5 - (current_time.minute % 5), "minutes and 0 seconds")
        else:
            print("Time to wait:", 4 - (current_time.minute % 5), "minutes and ", end="")
            print(60 - (current_time.second % 60), "seconds")

        time.sleep( (4 -(current_time.minute % 5))*60 + 60 -(current_time.second % 60))

        ran_once = False

The above code runs at intervals of 5 minutes. Initially, the main thread sleeps for the number of seconds required to reach the perfect timestamp. For example, if the program is started at 7:28:30 then it is going to sleep for 90 seconds and then start at 7:30:00. From then on it will wait for 5 minutes before it runs the required functionality again.

Also, I think the performance of firing up at the exact second really varies on how your system handles the threads.

Upvotes: 1

Bill Chen
Bill Chen

Reputation: 1749

You can use datetime and condition.

import datetime

while True:
    current_time = datetime.datetime.now()
    if current_time.second % 5 == 0 and current_time.minute % 1 == 0 and current_time.microsecond == 0:

        print(current_time)

enter image description here

hope this helps.

Upvotes: 1

Related Questions