Reputation: 1359
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
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
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
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
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)
hope this helps.
Upvotes: 1