Recipe3.10.Running a Command Repeatedly


Recipe 3.10. Running a Command Repeatedly

Credit: Philip Nunez

Problem

You need to run a command repeatedly, with arbitrary periodicity.

Solution

The time.sleep function offers a simple approach to this task:

import time, os, sys def main(cmd, inc=60):     while True:         os.system(cmd)         time.sleep(inc) 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

You can use this recipe with a command that periodically checks for something (e.g., polling), or with one that performs an endlessly repeating action, such as telling a browser to reload a URL whose contents change often, so as to always have a recent version of that URL for viewing. The recipe is structured into a function called main and a body that is preceded by the usual if _ _name_ _=='_ _main_ _': idiom, to execute only if the script runs as a main script. The body examines the command-line arguments you used with the script and calls main appropriately (or gives a usage message if there are too many or too few arguments). This is the best way to structure a script, to make its functionality also available to other scripts that may import it as a module.

The main function accepts a cmd string, which is a command you want to pass periodically to the operating system's shell, and, optionally, a period of time in seconds, with a default value of 60 (one minute). main loops forever, alternating between executing the command with os.system and waiting (without consuming resources) with time.sleep.

The script's body looks at the command-line arguments you used with the script, which it finds in sys.argv. The first argument, sys.argv[0], is the name of the script, often useful when the script identifies itself as it prints out messages. The body checks that one or two other arguments, in addition to this name, are included. The first (and mandatory) is the command to be run. (You may need to enclose this command in quotes to preserve it from your shell's parsing: the important thing is that it must remain a single argument.) The second (and optional) argument is the delay in seconds between two runs of the command. If the second argument is missing, the body calls main with just the command argument, accepting the default delay (60 seconds).

Note that, if there is a second argument, the body transforms it from a string (all items in sys.argv are always strings) into an integer, which is done most simply by calling built-in type int:

inc = int(sys.argv[2])

If the second argument is a string that is not acceptable for transformation into an integer (in other words, if it's anything except a sequence of digits), this call to int raises an exception and terminates the script with appropriate error messages. As one of Python's design principles states, "errors should not pass silently, unless explicitly silenced." It would be bad design to let the script accept an arbitrary string as its second argument, silently taking a default action if that string was not a correct integer representation!

For a variant of this recipe that uses the standard Python library module sched, rather than explicit looping and sleeping, see Recipe 3.11.

See Also

Documentation of the standard library modules os, time, and sys in the Library Reference and Python in a Nutshell; Recipe 3.11.



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