Skip to content Skip to sidebar Skip to footer

Schedule Code To Execute At Some Time Later

How can I schedule some code to be executed at a certain time later? I tried: import time import datetime time.sleep(420) print(datetime.datetime.now()) But this doesn't work if

Solution 1:

Your best option is to use cron or Apple's launchd. Since you want whatever it is to be executed at set intervals without a delay after waking up from sleep this is what I recommend.

Cron Method

To setup a new cron job you would open up Terminal and edit it with the time information and script you are wanting to execute (eg. every 7 minutes):

$ crontab -e

*/7 * * * * /usr/bin/python /path/to/myscript.py

Here's a quick breakdown of the meaning:

*****  command toexecute
│ │ │ │ │
│ │ │ │ └─── dayof week (0-6) (0to6are Sunday to Saturday, or use names; 7is Sunday, the same as0)
│ │ │ └──────── month (1-12)
│ │ └───────────── dayofmonth (1-31)
│ └────────────────── hour (0-23)
└─────────────────────── min (0-59)

To list jobs you have set in your crontab:

$ crontab -l

Timed Jobs Using launchd

Apple's recommendation is not to use crontab, rather launchd. Basically this entails creating a preference list with the information about your task and what time to run it, etc.

$ cd $HOME/Library/LaunchAgents
$ nano com.username.mytask.plist

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plistPUBLIC"-//Apple//DTD PLIST 1.0//EN""http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plistversion="1.0"><dict><key>Label</key><string>com.username.mytask</string><key>ProgramArguments</key><array><string>/path/to/myscript.sh</string></array><key>StartInterval</key><integer>7</integer><key>RunAtLoad</key><true/></dict></plist>

In nano press Control + O followed by Control + X to save.

$ chmod +x /path/to/myscript.sh$ launchctl load com.username.mytask.plist$ launchctl start com.username.mytask.plist

The following would make your script executable, and then load and start the launch agent.

To stop and unload:

$ launchctl stop com.username.mytask.plist
$ launchctl unload com.username.mytask.plist

More information:

Scheduling Timed JobsCreating a launchd Property List File

Effects of Sleeping and Powering Off

If the system is turned off or asleep, cron jobs do not execute; they will not run until the next designated time occurs.

If you schedule a launchd job by setting the StartCalendarInterval key and the computer is asleep when the job should have run, your job will run when the computer wakes up. However, if the machine is off when the job should have run, the job does not execute until the next designated time occurs.

All other launchd jobs are skipped when the computer is turned off or asleep; they will not run until the next designated time occurs.

Consequently, if the computer is always off at the job’s scheduled time, both cron jobs and launchd jobs never run. For example, if you always turn your computer off at night, a job scheduled to run at 1 A.M. will never be run.

Solution 2:

sched module is a generally useful event scheduler. It can schedule events in the future by relative (enter method) or absolute time (enterabs method) with priority.

As time.sleep uses select syscall on Linux which introduces delays we have to define a sleep function based on time.time which doesn't suffer from the unnecessary delay.

from __future__ import print_function
import sched
from datetime import datetime
fromtime import sleep, time

def my_sleep(n):
    s = time()
    while (time() - s) < n:
        # introduce small delay for optimization
        sleep(0.1)

schedule = sched.scheduler(time, my_sleep)
schedule.enter(2, 0, lambda: print(datetime.now()), ())
schedule.enter(3, 0, lambda: print(datetime.now()), ())
schedule.run()

Solution 3:

EDIT From the man page for "atrun" Execute the following command as root to enable atrun:

launchctl load -w /System/Library/LaunchDaemons/com.apple.atrun.plist  

then something like:

at now + 5 minutes
echo'testing the at command' > myfile.txt
<EOD>  

See the man page for "at" for other options

Solution 4:

Update: User @I'L'I pointed out that there was an error in my code. In copy pasting the wait_time variable, I overwrote a necessary seconds= in timedelta which prevented the loop from ever exiting. This is now fixed.

Your code waits until the program has run for a set number of seconds. You don't actually want that, according to your Question, correct? You actually want to wait until a certain number of seconds have passed from your start time, and continue at the first opportunity after they have passed.

Do this:

from datetime import datetime
from datetime import timedelta

# Establish the start time as a static variable. Basically lock the start time in.
start_time = datetime.now()

# How long should we wait?
wait_time = 420# What should I say while I wait?
wait_string = "Zzzzzzzzzzz"# Loop until at least wait_time seconds have passedwhile datetime.now() <= start_time + timedelta(seconds=wait_time):
    print(wait_string, end = "\r"),

print("Done waiting at:", datetime.now())

Post a Comment for "Schedule Code To Execute At Some Time Later"