Trigger a Python function exactly on the minute
Solution 1
You might try APScheduler, a cron-style scheduler module for Python.
From their examples:
from apscheduler.scheduler import Scheduler
# Start the scheduler
sched = Scheduler()
sched.start()
def job_function():
print "Hello World"
sched.add_cron_job(job_function, second=0)
will run job_function
every minute.
Solution 2
What if you measured how long it took your code to execute, and subtracted that from a sleep time of 60?
import time
while True:
timeBegin = time.time()
CODE(.....)
timeEnd = time.time()
timeElapsed = timeEnd - timeBegin
time.sleep(60-timeElapsed)
Solution 3
The simplest solution would be to register a timeout with the operating system to expire when you want it to.
Now there are quite a few ways to do so with a blocking instruction and the best option depends on your implementation. Simplest way would be to use time.sleep()
:
import time
current_time = time.time()
time_to_sleep = 60 - (current_time % 60)
time.sleep(time_to_sleep)
This way you take the current time and calculate the amount of time you need to sleep (in seconds). Not millisecond accurate but close enough.
Solution 4
APScheduler is the correct approach. The syntax has changed since the original answer, however.
As of APScheduler 3.3.1:
def fn():
print("Hello, world")
from apscheduler.schedulers.background import BackgroundScheduler
scheduler = BackgroundScheduler()
scheduler.start()
scheduler.add_job(fn, trigger='cron', second=0)
Solution 5
You can try Threading.Timer
See this Example
from threading import Timer
def job_function():
Timer(60, job_function).start ()
print("Running job_funtion")
It will print "Running job_function" every Minute
Edit: If we are critical about the time at which it should run
from threading import Timer
from time import time
def job_function():
Timer(int(time()/60)*60+60 - time(), job_function).start ()
print("Running job_funtion")
It will run exactly at 0th second of every minute.
![Admin](/assets/logo_square_200-5d0d61d6853298bd2a4fe063103715b4daf2819fc21225efa21dfb93e61952ea.png)
Admin
Updated on June 18, 2022Comments
-
Admin about 2 years
I have a function that I want to trigger at every turn of the minute — at 00 seconds. It fires off a packet over the air to a dumb display that will be mounted on the wall.
I know I can brute force it with a while loop but that seems a bit harsh.
I have tried using sched but that ends up adding a second every minute.
What are my options?
-
tdelaney over 10 yearsThis doesn't account for the time that f(x) takes and so it will have a similar "adding a second every minute" problem the poster wants to avoid.
-
Jordan over 7 yearsThere's a possibility that 60-timeElapsed could be negative, which throws an IOError. time.sleep(max(0, 60-timeElapsed)) can fix that.
-
theonlygusti over 7 yearsDoes time.sleep work even if the operating system/computer sleeps?
-
immortal over 7 years@theonlygusti I doubt that... When the computer sleeps no application can get CPU time as the CPU is also asleep. There are HW interrupts that could wake the computer up, usually a mechanism wired to the Laptop's display and detects the computer was opened, and many network cards can issue such an interrupt by receiving a packet / access through IPMI interface. The time.sleep function, however, requests the operating system to suspend execution for a period of time. It will not issue a wakeup call to the entire machine.
-
chjortlund about 6 yearsGreat module, the syntax has changed since the answer, see: apscheduler.readthedocs.io/en/v3.5.1/modules/schedulers/… and apscheduler.readthedocs.io/en/v3.5.1/modules/triggers/cron.html