Start a Function at Given Time

Question:

How can I run a function in Python, at a given time?

For example:

run_it_at(func, '2012-07-17 15:50:00')

and it will run the function func at 2012-07-17 15:50:00.

I tried the sched.scheduler, but it didn’t start my function.

import time as time_module
scheduler = sched.scheduler(time_module.time, time_module.sleep)
t = time_module.strptime('2012-07-17 15:50:00', '%Y-%m-%d %H:%M:%S')
t = time_module.mktime(t)
scheduler_e = scheduler.enterabs(t, 1, self.update, ())

What can I do?

Asked By: microo8

||

Answers:

Reading the docs from http://docs.python.org/py3k/library/sched.html:

Going from that we need to work out a delay (in seconds)…

from datetime import datetime
now = datetime.now()

Then use datetime.strptime to parse ‘2012-07-17 15:50:00’ (I’ll leave the format string to you)

# I'm just creating a datetime in 3 hours... (you'd use output from above)
from datetime import timedelta
run_at = now + timedelta(hours=3)
delay = (run_at - now).total_seconds()

You can then use delay to pass into a threading.Timer instance, eg:

threading.Timer(delay, self.update).start()
Answered By: Jon Clements

Take a look at the Advanced Python Scheduler, APScheduler: http://packages.python.org/APScheduler/index.html

They have an example for just this usecase:
http://packages.python.org/APScheduler/dateschedule.html

from datetime import date
from apscheduler.scheduler import Scheduler

# Start the scheduler
sched = Scheduler()
sched.start()

# Define the function that is to be executed
def my_job(text):
    print text

# The job will be executed on November 6th, 2009
exec_date = date(2009, 11, 6)

# Store the job in a variable in case we want to cancel it
job = sched.add_date_job(my_job, exec_date, ['text'])
Answered By: stephenbez

I ran into the same issue: I could not get absolute time events registered with sched.enterabs to be recognized by sched.run. sched.enter worked for me if I calculated a delay, but is awkward to use since I want jobs to run at specific times of day in particular time zones.

In my case, I found that the issue was that the default timefunc in the sched.scheduler initializer is not time.time (as in the example), but rather is time.monotonic. time.monotonic does not make any sense for “absolute” time schedules as, from the docs, “The reference point of the returned value is undefined, so that only the difference between the results of consecutive calls is valid.”

The solution for me was to initialize the scheduler as

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

It is unclear whether your time_module.time is actually time.time or time.monotonic, but it works fine when I initialize it properly.

Answered By: Eric Westphal
dateSTR = datetime.datetime.now().strftime("%H:%M:%S" )
if dateSTR == ("20:32:10"):
   #do function
    print(dateSTR)
else:
    # do something useful till this time
    time.sleep(1)
    pass

Just looking for a Time of Day / Date event trigger:
as long as the date “string” is tied to an updated “time” string, it works as a simple TOD function. You can extend the string out to a date and time.

whether its lexicographical ordering or chronological order comparison,
as long as the string represents a point in time, the string will too.

someone kindly offered this link:

String Comparison Technique Used by Python

Answered By: mAd

Might be worth installing this library: https://pypi.python.org/pypi/schedule, basically helps do everything you just described. Here’s an example:

import schedule
import time

def job():
    print("I'm working...")

schedule.every(10).minutes.do(job)
schedule.every().hour.do(job)
schedule.every().day.at("10:30").do(job)
schedule.every().monday.do(job)
schedule.every().wednesday.at("13:15").do(job)

while True:
    schedule.run_pending()
    time.sleep(1)
Answered By: daniel galarza

Here’s an update to stephenbez’ answer for version 3.5 of APScheduler using Python 2.7:

import os, time
from apscheduler.schedulers.background import BackgroundScheduler
from datetime import datetime, timedelta


def tick(text):
    print(text + '! The time is: %s' % datetime.now())


scheduler = BackgroundScheduler()
dd = datetime.now() + timedelta(seconds=3)
scheduler.add_job(tick, 'date',run_date=dd, args=['TICK'])

dd = datetime.now() + timedelta(seconds=6)
scheduler.add_job(tick, 'date',run_date=dd, kwargs={'text':'TOCK'})

scheduler.start()
print('Press Ctrl+{0} to exit'.format('Break' if os.name == 'nt' else 'C'))

try:
    # This is here to simulate application activity (which keeps the main thread alive).
    while True:
        time.sleep(2)
except (KeyboardInterrupt, SystemExit):
    # Not strictly necessary if daemonic mode is enabled but should be done if possible
    scheduler.shutdown()
Answered By: user1106278

I’ve confirmed the code in the opening post works, just lacking scheduler.run(). Tested and it runs the scheduled event. So that is another valid answer.

>>> import sched
>>> import time as time_module
>>> def myfunc(): print("Working")
...
>>> scheduler = sched.scheduler(time_module.time, time_module.sleep)
>>> t = time_module.strptime('2020-01-11 13:36:00', '%Y-%m-%d %H:%M:%S')
>>> t = time_module.mktime(t)
>>> scheduler_e = scheduler.enterabs(t, 1, myfunc, ())
>>> scheduler.run()
Working
>>>
Answered By: SlowBro

had a really hard time getting these answers to work how i needed it to,

but i got this working and its accurate to .01 seconds

from apscheduler.schedulers.background import BackgroundScheduler
    
sched = BackgroundScheduler()
sched.start()

def myjob():
    print('job 1 done at: ' + str(dt.now())[:-3])

dt = datetime.datetime
Future = dt.now() + datetime.timedelta(milliseconds=2000)
job = sched.add_job(myjob, 'date', run_date=Future)

tested accuracy of timing with this code:
at first i did 2 second and 5 second delay, but wanted to test it with a more accurate measurement so i tried again with 2.55 second delay and 5.55 second delay

dt = datetime.datetime
Future = dt.now() + datetime.timedelta(milliseconds=2550)
Future2 = dt.now() + datetime.timedelta(milliseconds=5550)

def myjob1():
    print('job 1 done at: ' + str(dt.now())[:-3])
def myjob2():
    print('job 2 done at: ' + str(dt.now())[:-3])

print(' current time: ' + str(dt.now())[:-3])
print('  do job 1 at: ' + str(Future)[:-3] + ''' 
  do job 2 at: ''' + str(Future2)[:-3])
job = sched.add_job(myjob1, 'date', run_date=Future)
job2 = sched.add_job(myjob2, 'date', run_date=Future2)

and got these results:

 current time: 2020-12-10 19:50:44.632
  do job 1 at: 2020-12-10 19:50:47.182 
  do job 2 at: 2020-12-10 19:50:50.182
job 1 done at: 2020-12-10 19:50:47.184
job 2 done at: 2020-12-10 19:50:50.183

accurate to .002 of a second with 1 test

but i did run a lot of tests and accuracy ranged from .002 to .011

never going under the 2.55 or 5.55 second delay

Answered By: monty314thon
#everytime you print action_now it will check your current time and tell you should be done

import datetime  
current_time = datetime.datetime.now()  
current_time.hour  

schedule = {
    '8':'prep',
    '9':'Note review',
    '10':'code',
    '11':'15 min teabreak ',
    '12':'code',
    '13':'Lunch Break',
    '14':'Test',
    '15':'Talk',
    '16':'30 min for code ',
    '17':'Free',
    '18':'Help ',
    '19':'watever',
    '20':'watever',
    '21':'watever',
    '22':'watever'
}

action_now = schedule[str(current_time.hour)]
Answered By: Zoe
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.