Trigger a Python function exactly on the minute

18,089

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.

Share:
18,089
Admin
Author by

Admin

Updated on June 18, 2022

Comments

  • Admin
    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
    tdelaney over 10 years
    This 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
    Jordan over 7 years
    There's a possibility that 60-timeElapsed could be negative, which throws an IOError. time.sleep(max(0, 60-timeElapsed)) can fix that.
  • theonlygusti
    theonlygusti over 7 years
    Does time.sleep work even if the operating system/computer sleeps?
  • immortal
    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
    chjortlund about 6 years