You are here: Home > Dive Into Python > XML Processing > Handling command line arguments | << >> | ||||
Dive Into PythonPython for experienced programmers |
Python fully supports creating programs that can be run on the command line, complete with command-line arguments and either short- or long-style flags to specify various options. None of this is XML-specific, but this script makes good use of command-line processing, so it seemed like a good time to mention it.
It’s difficult to talk about command line processing without understanding how command line arguments are exposed to your Python program, so let’s write a simple program to see them.
If you have not already done so, you can download this and other examples used in this book.
#argecho.py import sys for arg in sys.argv: print arg
[f8dy@oliver py]$ python argecho.py argecho.py [f8dy@oliver py]$ python argecho.py abc def argecho.py abc def [f8dy@oliver py]$ python argecho.py --help argecho.py --help [f8dy@oliver py]$ python argecho.py -m kant.xml argecho.py -m kant.xml
The first thing to know about sys.argv is that it contains the name of the script we’re calling. We will actually use this knowledge to our advantage later, in Data-Centric Programming. Don’t worry about it for now. | |
Command line arguments are separated by spaces, and each shows up as a separate element in the sys.argv list. | |
Command line flags, like --help, also show up as their own element in the sys.argv list. | |
To make things even more interesting, some command line flags themselves take arguments. For instance, here we have a flag (-m) which takes an argument (kant.xml). Both the flag itself and the flag’s argument are simply sequential elements in the sys.argv list. No attempt is made to associate one with the other; all you get is a list. |
So as we can see, we certainly have all the information passed on the command line, but then again, it doesn’t look like it’s going to be all that easy to actually use it. For simple programs that only take a single argument and have no flags, you can simply use sys.argv[1] to access the argument. There’s no shame in this; I do it all the time. For more complex programs, you need the getopt module.
def main(argv): grammar = "kant.xml" try: opts, args = getopt.getopt(argv, "hg:d", ["help", "grammar="]) except getopt.GetoptError: usage() sys.exit(2) ... if __name__ == "__main__": main(sys.argv[1:])
So what are all those parameters we pass to the getopt function? Well, the first one is simply the raw list of command line flags and arguments (not including the first element, the script name, which we already chopped off before calling our main function). The second is the list of short command line flags that our script accepts.
The first and third flags are simply standalone flags; you specify them or you don’t, and they do things (print help) or change state (turn on debugging). However, the second flag (-g) must be followed by an argument, which is the name of the grammar file to read from. In fact it can be a filename or a web address, and we don’t know which yet (we’ll figure it out later), but we know it has to be something. So we tell getopt this by putting a colon after the g in that second parameter to the getopt function.
To further complicate things, our script accepts either short flags (like -h) or long flags (like --help), and we want them to do the same thing. This is what the third parameter to getopt is for, to specify a list of the long flags that correspond to the short flags we specified in the second parameter.
Three things of note here:
Confused yet? Let’s look at the actual code and see if it makes sense in context.
def main(argv): grammar = "kant.xml" try: except getopt.GetoptError: usage() sys.exit(2) for opt, arg in opts: if opt in ("-h", "--help"): usage() sys.exit() elif opt == '-d': global _debug _debug = 1 elif opt in ("-g", "--grammar"): grammar = arg source = "".join(args) k = KantGenerator(grammar, source) print k.output()
<< Creating separate handlers by node type |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | |
Putting it all together >> |