thisishardtoread

code, thoughts, and learnings

github.com/arbylee

Parsing command line options in Python

30 Apr 2014

Despite the prevalence of graphical interfaces and the growing demand for stunning visualizations, sometimes the simplicity of a command line client is all you need. Fortunately with Python’s argparse, you can quickly pull one together with short/long name aliasing, spiffy help text, and other familiar command line features. However, the docs can be a lengthy read, so here’s a quick rundown.

Let’s start with an example app with only positional args:

# calculator.py
import argparse

parser = argparse.ArgumentParser(description='A calculator')
parser.add_argument('number',
                    type=float,
                    nargs="*",
                    help='Numbers to add together')

args = parser.parse_args()

print(sum(args.number))

# python calculator.py       # 0
# python calculator.py 1 2   # 3.0
# python calculator.py 3 6 7 # 16.0

With this snippet, we have a simple calculator that collects a series of numbers and sums them for us. The type option lets argparse know what kind of value to expect when parsing, and the nargs option specifies how many arguments to expect. Here we’re grabbing all positional arguments and lumping them together by setting nargs="*". Of course if you’re expecting a specific number of arguments, you can always pass in an integer.

argparse also gives us a snazzy help menu for free, which you can see by running python calculator.py --help:

usage: calculator.py [-h] [number [number ...]]

A calculator

positional arguments:
  number      Numbers to add together

optional arguments:
  -h, --help  show this help message and exit

Now that we’ve got a positional arg, let’s add some more functionality.

# calculator.py
import argparse
import operator

parser = argparse.ArgumentParser(description='A calculator')
# Accept several positional args and store them as "number"
parser.add_argument('number', type=float, nargs="*",
                    help='Numbers to add together')

# Accept a verbose True/False flag
parser.add_argument('-v',
                    '--verbose',
                    action='store_true',
                    help='Print more verbose output')

# Accept an operation parameter
parser.add_argument('-o',
                    '--operation',
                    type=str,
                    default='sum',
                    choices=['sum', 'multiply'],
                    help='The type of operation to perform')

args = parser.parse_args()

if args.operation == 'multiply':
    answer = reduce(operator.mul, args.number, 1)
elif args.operation == 'sum':
    answer = sum(args.number)

if args.verbose:
    print("Some more verbose output")
    print(args)

print(answer)

Now we can either sum or multiply the numbers together by specifying an operation, and we can print out additional output with the verbose argument. Let’s take a quick look at these new arguments, starting with verbose:

parser.add_argument('-v',
                    '--verbose',
                    action='store_true',
                    help='Print more verbose output')

The verbose argument is fairly straightforward. The two positional arguments declare a short name -v and a long name --verbose, and by specifying action='store_true', argparse will store True if the argument is given and default to False otherwise.

python calculator.py 3 6 --verbose # args.verbose == True
python calculator.py 3 6 -v        # args.verbose == True
python calculator.py 3 6           # args.verbose == False

As for the operation argument:

parser.add_argument('-o',
                    '--operation',
                    type=str,
                    choices=['sum', 'multiply'],
                    default='sum',
                    help='The type of operation to perform')

Our first two arguments declare a short name -o and a long name –operation. Next we specify type=str so that argparse will parse the value to a string for us. Then we limit the valid values of the argument to sum and multiply, defaulting the value to sum if nothing is given. Lastly since we didn’t specify an action, argparse will use the default store action and just hold onto the value for us.

python calculator.py 3 6                      # args.operation == 'sum'
python calculator.py 3 6 -o sum               # args.operation == 'sum'
python calculator.py 3 6 --operation multiply # args.operation == 'multiply'
python calculator.py 3 6 --operation foobar   # throws an error

Other than store and store_true, there are a handful of other actions that argparse provides as well; you can even roll your own custom action. And there’s still more that argparse can offer, but this should be enough to get you through most of your parsing needs.