When you write code, whether in Python or some other language, you probably have a goal that you or someone else will one day run it. A very common, useful, and powerful option for running your code is to call it from a command line. Writing your code so that it runs from the command line is easy. In fact, you don't have to do anything special to get it working on the command line.
If you've spent even a trivial amount of time on the command line, particularly a UNIX shell, you may have noticed that when you run a utility, you are often able to specify various runtime parameters that change the utility's runtime behavior. For example, if you've ever used the UNIX ls utility, you probably know that you can modify the way it outputs the files and directories that it matches by giving it a parameter, such as -l. These parameters are also called "options".
Here is a plain ls command:
$ ls ZConfig-2.6.0-py2.5.egg zdaemon-2.0.2-py2.5.egg ZODB3-3.8.1b7-py2.5-macosx-10.5-i386.egg zope.interface-3.4.1-py2.5-macosx-10.5-i386.egg easy-install.pth zope.proxy-3.4.2-py2.5-macosx-10.5-i386.egg setuptools-0.6c8-py2.5.egg zope.testing-3.6.0-py2.5.egg setuptools.pth
And here is ls -l (or long listing):
$ ls -l total 656 drwxr-xr-x 4 jmjones staff 136 Sep 16 08:25 ZConfig-2.6.0-py2.5.egg drwxr-xr-x 10 jmjones staff 340 Sep 16 08:25 ZODB3-3.8.1b7-py2.5-macosx-10.5-i386.egg -rw-r--r-- 1 jmjones staff 494 Sep 16 08:26 easy-install.pth -rwxr-xr-x 1 jmjones staff 324858 Jun 19 19:05 setuptools-0.6c8-py2.5.egg -rw-r--r-- 1 jmjones staff 29 Sep 16 08:23 setuptools.pth drwxr-xr-x 4 jmjones staff 136 Sep 16 08:25 zdaemon-2.0.2-py2.5.egg drwxr-xr-x 4 jmjones staff 136 Sep 16 08:25 zope.interface-3.4.1-py2.5-macosx-10.5-i386.egg drwxr-xr-x 4 jmjones staff 136 Sep 16 08:25 zope.proxy-3.4.2-py2.5-macosx-10.5-i386.egg drwxr-xr-x 4 jmjones staff 136 Sep 16 08:25 zope.testing-3.6.0-py2.5.egg
Both runs of the ls utility listed the same files. However, ls -l listed more information than ls.
Have you ever wondered how you could create utilities that had a rich command line interface? This article will show you how to use Python to do just that.
First, you'll need to understand how your scripts handle the command line arguments from a user. If I run the following script with some random command line arguments, it will show how Python treats those arguments. Here is the script.
#!/usr/bin/env python import sys print "sys.argv", sys.argv
And here is an example of running the script.
$ ./argv.py foo bar bam sys.argv ['./argv.py', 'foo', 'bar', 'bam']
The command line arguments are treated as a list, which is accessible by referencing sys.argv. The first element of the list is the name of the script and the remaining elements are the arguments passed in after the script name. If I wanted to, I could figure out what options I wanted to take, iterate through sys.argv, and map what the user gave me to the options I wanted to handle. I could do that, but it would be wasted time.
There is a better way. A much better way. It's called optparse.
With optparse, you declaratively build up an option parser by adding the behavior you want it to exhibit when it sees various options. Here's a simple example of a script that uses optparse.
#!/usr/bin/env python from optparse import OptionParser usage = "usage: %prog [options]" parser = OptionParser(prog='testprog', usage=usage) parser.add_option('-t', '--true', dest='true', action='store_true', help='example of using store_true, default %default') parser.add_option('-v', '--value', dest='value', action='store', help='example of using multiple arguments') parser.set_defaults(true=False ) options, args = parser.parse_args() print 'OPTIONS::', options print 'ARGS::', args
The basics of optparse are as follows:
Create an instance of the OptionParser
Add options to it that will handle various command line arguments passed in from the user
Set any default values for any of the options
Tell the parser to parse the arguments from sys.argv
In the previous script, I created an instance of the OptionParser class and named it parser. Then I added an option so that if the script is called with a -t or --true option, it will store a True value for that particular option attribute. I also added an option so that users can pass in either a -v or --value followed by an argument and have that argument stored for later use.
The action keyword in the add_option() method specifies how the value will be handled. store_true expects no arguments and will just set the specified dest attribute to True. store (which is the default if no action is specified) expects a value and will store that value in the dest attribute. Other actions include store_false, count, store_const, and append.