Schedule Code To Execute At Some Time Later
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 Jobs ↳ Creating 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 necessaryseconds=
intimedelta
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"