Recipe3.11.Scheduling Commands


Recipe 3.11. Scheduling Commands

Credit: Peter Cogolo

Problem

You need to schedule commands for execution at certain times.

Solution

That's what the sched module of the standard library is for:

import time, os, sys, sched schedule = sched.scheduler(time.time, time.sleep) def perform_command(cmd, inc):     schedule.enter(inc, 0, perform_command, (cmd, inc)) # re-scheduler     os.system(cmd) def main(cmd, inc=60):     schedule.enter(0, 0, perform_command, (cmd, inc))   # 0==right now     schedule.run( ) if _ _name_ _ == '_ _main_ _' :     numargs = len(sys.argv) - 1     if numargs < 1 or numargs > 2:         print "usage: " + sys.argv[0] + " command [seconds_delay]"         sys.exit(1)     cmd = sys.argv[1]     if numargs < 3:         main(cmd)     else:         inc = int(sys.argv[2])         main(cmd, inc)

Discussion

This recipe implements the same functionality as in the previous Recipe 3.10, but instead of that recipe's simpler roll-our-own approach, this one uses the standard library module sched.

sched is a reasonably simple, yet flexible and powerful, module for scheduling tasks that must take place at given times in the future. To use sched, you first instantiate a scheduler object, such as schedule (shown in this recipe's Solution), with two arguments. The first argument is the function to call in order to find out what time it isnormally time.time, which returns the current time as a number of seconds from an arbitrary reference point known as the epoch. The second argument is the function to call to wait for some timenormally time.sleep. You can also pass functions that measure time in arbitrary artificial ways. For example, you can use sched for such tasks as simulation programs. However, measuring time in artificial ways is an advanced use of sched not covered in this recipe.

Once you have a sched.scheduler instance s, you schedule events by calling either s.enter, to schedule something at a relative time n seconds from now (you can pass n as 0 to schedule something for right now), or s.enterabs, to schedule something at a given absolute time. In either case, you pass the time (relative or absolute), a priority (if multiple events are scheduled for the same time, they execute in priority order, lowest-priority first), a function to call, and a tuple of arguments to call that function with. Each of these two methods return an event identifier, an arbitrary token that you may store somewhere and later use to cancel a scheduled event by passing the event's token as the argument in a call to s.cancelanother advanced use which this recipe does not cover.

After scheduling some events, you call s.run, which keeps running until the queue of scheduled events is empty. In this recipe, we show how to schedule a periodic, recurring event: function perform_command reschedules itself for inc seconds later in the future as the first thing it does, before running the specified system command. In this way, the queue of scheduled events never empties, and function perform_command keeps getting called with regular periodicity. This self-rescheduling is an important idiom, not just in using sched, but any time you have a "one-shot" way to ask for something to happen in the future, and you need instead to have something happen in the future "periodically". (Tkinter's after method, e.g., also works in exactly this way, and thus is also often used with just this kind of self-rescheduling idiom.)

Even for a task as simple as the one handled by this recipe, sched still has a small advantage over the simpler roll-your-own approach used previously in Recipe 3.10. In Recipe 3.10, the specified delay occurs between the end of one execution of cmd and the beginning of the next execution. If the execution of cmd takes a highly variable amount of time (as is often the case, e.g., for commands that must wait for the network, or some busy server, etc.), then the command is not really being run periodically. In this recipe, the delay occurs between beginning successive runs of cmd, so that periodicity is indeed guaranteed. If a certain run of cmd takes longer than inc seconds, the schedule temporarily falls behind, but it will eventually catch up again, as long as the average running time of cmd is less than inc seconds: sched never "skips" events. (If you do want an event to be skipped because it's not relevant any more, you have to keep track of the event identifier token and use the cancel method.)

For a detailed explanation of this script's structure and body, see Recipe 3.10.

See Also

Recipe 3.10; documentation of the standard library modules os, time, sys, and sched in the Library Reference and Python in a Nutshell.



Python Cookbook
Python Cookbook
ISBN: 0596007973
EAN: 2147483647
Year: 2004
Pages: 420

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net