Parse arguments with Python

Parse Python like a pro with the argparse module.
130 readers like this.
What to like about COBOL

Rainer Gerhards. Modified by Opensource.com. CC BY-SA 4.0

If you're using Python for any amount of development, you have probably issued a command in a terminal, even if only to launch a Python script or install a Python module with pip. Commands may be simple and singular:

$ ls

Commands also might take an argument:

$ ls example

Commands can also have options or flags:

$ ls --color example

Sometimes options also have arguments:

$ sudo firewall-cmd  --list-all --zone home

Arguments

The POSIX shell automatically splits whatever you type as a command into an array. For instance, here is a simple command:

$ ls example

The command ls is position $0, and the argument example is in position $1.

You could write a loop to iterate over each item; determine whether it is the command, an option, or an argument; and take action accordingly. Luckily, a module called argparse already exists for that.

Argparse

The argparse module is easy to integrate into your Python programs and has several convenience features. For instance, if your user changes the order of options or uses one option that takes no arguments (called a Boolean, meaning the option toggles a setting on or off) and then another that requires an argument (such as --color red, for example), argparse can handle the variety. If your user forgets an option that's required, the argparse module can provide a friendly error message.

Using argparse in your application starts with defining what options you want to provide your user. There are several different kinds of arguments you can accept, but the syntax is consistent and simple.

Here's a simple example:

#!/usr/bin/env python
import argparse
import sys

def getOptions(args=sys.argv[1:]):
    parser = argparse.ArgumentParser(description="Parses command.")
    parser.add_argument("-i", "--input", help="Your input file.")
    parser.add_argument("-o", "--output", help="Your destination output file.")
    parser.add_argument("-n", "--number", type=int, help="A number.")
    parser.add_argument("-v", "--verbose",dest='verbose',action='store_true', help="Verbose mode.")
    options = parser.parse_args(args)
    return options

This code sample creates a function called getOptions and tells Python to look at each potential argument preceded by some recognizable string (such as --input or -i). Any option that Python finds is returned out of the function as an options object (options is an arbitrary name and has no special meaning; it's just a data object containing a summary of all the arguments that the function has parsed).

By default, any argument given by the user is seen by Python as a string. If you need to ingest an integer (a number), you must specify that an option expects type=int, as in the --number option in the sample code.

If you have an argument that just turns a feature on or off, then you must use the boolean type, as with the --verbose flag in the sample code. This style of option simply stores True or False, specifying whether or not the user used the flag. If the option is used, then stored_true is activated.

Once the getOptions function runs, you can use the contents of the options object and have your program make decisions based on how the user invoked the command. You can see the contents of options with a test print statement. Add this to the bottom of your example file:

print(getOptions())

Then run the code with some arguments:

$ python3 ./example.py -i foo -n 4
Namespace(input='foo', number=4, output=None, verbose=False)

Retrieving values

The options object in the sample code contains any value provided by the user (or a derived Boolean value) in keys named after the long option. In the sample code, for instance, the --number option can be retrieved by looking at options.number.

options = getOptions(sys.argv[1:])

if options.verbose: 
    print("Verbose mode on")
else:
    print("Verbose mode off")

print(options.input)
print(options.output)
print(options.number)

# Insert Useful Python Code Here...

The Boolean option, --verbose in the example, is determined by testing whether options.verbose is True (meaning the user did use the --verbose flag) or False (the user did not use the --verbose flag), and taking some action accordingly.

Help and feedback

Argparse also includes a built-in --help (-h for short) option that provides a helpful tip on how the command is used. This is derived from your code, so it takes no extra work to generate this help system:

$ ./example.py --help
usage: example.py [-h] [-i INPUT] [-o OUTPUT] [-n NUMBER] [-v]

Parses command.

optional arguments:
  -h, --help            show this help message and exit
  -i INPUT, --input INPUT
                        Your input file.
  -o OUTPUT, --output OUTPUT
                        Your destination output file.
  -n NUMBER, --number NUMBER
                        A number.
  -v, --verbose         Verbose mode.

Python parsing like a pro

This a simple example that demonstrates how to deal with parsing arguments in a Python application and how to quickly and efficiently document their syntax. The next time you write a quick Python script, give it some options with argparse. You'll thank yourself later, and your command will feel less like a quick hack and more like a "real" Unix command!

Here's the sample code, which you can use for testing:


#!/usr/bin/env python3
# GNU All-Permissive License
# Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided the copyright
# notice and this notice are preserved.  This file is offered as-is,
# without any warranty.

import argparse
import sys

def getOptions(args=sys.argv[1:]):
    parser = argparse.ArgumentParser(description="Parses command.")
    parser.add_argument("-i", "--input", help="Your input file.")
    parser.add_argument("-o", "--output", help="Your destination output file.")
    parser.add_argument("-n", "--number", type=int, help="A number.")
    parser.add_argument("-v", "--verbose",dest='verbose',action='store_true', help="Verbose mode.")
    options = parser.parse_args(args)
    return options

options = getOptions(sys.argv[1:])

if options.verbose: 
    print("Verbose mode on")
else:
    print("Verbose mode off")

print(options.input)
print(options.output)
print(options.number)

 

Tags
Seth Kenlon
Seth Kenlon is a UNIX geek, free culture advocate, independent multimedia artist, and D&D nerd. He has worked in the film and computing industry, often at the same time.

4 Comments

I would use docopt from docopt.org
it parses the help you would have to write anyway, to handle options. It also works for multiple languages.

Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.