Use argparse to add command-line interface to a Python program

Last updated on 2021-12-12 Tagged under  # python  # programming

I know from previous experience writing a few bash scripts how useful and flexible it is to supply arguments and options to a script at runtime vs hardcoding everything in the script itself. Now that I've started learning Python in earnest, I've found the argparse module provides a simple method to do the same.

Scenario: I created a program - die_results.py - to simulate rolling dice and analyze the results. The first version contained a variable for a single 6-sided die, another variable specifying 1,000 to simulate that number of rolls, and returned the results as a list.

But how about 10,000 rolls, or 1 million rolls, or whatever number of rolls? What about, instead of a single die, rolling with multiple die? While we're at it, maybe change them from being 6-sided die to something different? How about an option to visualize the results in a graph vs returning a list?

Version 2 uses argparse to create a command-line interface to the program, enabling all these capabilities at runtime ...

$ die_results.py --help
usage: die_results.py [-h] [-g] [-n NUMBER] [-s SIDES] rolls

Analyze the results of rolling dice.

positional arguments:
  rolls                 number of rolls

optional arguments:
  -h, --help            show this help message and exit
  -g, --graph           visualize the results
  -n NUMBER, --number NUMBER
                        number of die
  -s SIDES, --sides SIDES
                        number of die sides

The --help option is a freebie provided directly by argparse.

Here is the code for the rest ...

import argparse

desc = "Analyze the results of rolling dice."
parser = argparse.ArgumentParser(description=desc)
parser.add_argument("rolls", help="number of rolls")
parser.add_argument("-g", "--graph", action="store_true",
                    help="visualize the results")
parser.add_argument("-n", "--number", help="number of die")
parser.add_argument("-s", "--sides", help="number of die sides")
args = parser.parse_args()

Breaking it down, first the argparse code is added to my own program code ...

import argparse

I create a parser object (including a description of the program's purpose) to process my command-line options and arguments ...

desc = "Analyze the results of rolling dice."
parser = argparse.ArgumentParser(description=desc)

A single, required positional argument specifies the number of die rolls ...

parser.add_argument("rolls", help="number of rolls")

There are also three optional arguments that can be used. One sets a flag condition to True, which generates a graph of the results ...

parser.add_argument("-g", "--graph", action="store_true",
                    help="visualize the results")

The other two options require an (integer) argument to set the number of die used and/or the number of sides of the die ...

parser.add_argument("-n", "--number", help="number of die")
parser.add_argument("-s", "--sides", help="number of die sides")

All specified options and arguments are stored in the args object ...

args = parser.parse_args()

Access an argument in the form of args.[name]. For example, an if-else conditional to decide whether to output results in a graph or a list ...

if args.graph:  # does this evaluate to 'True'?
    my_graph()
else:
    my_list()

Store the number of rolls in a variable ...

number_of_rolls = int(args.rolls)

In use: Simulate 10,000 rolls of a single six-sided die, and count the number of times each number appears ...

$ die_results.py 10_000
[1692, 1675, 1743, 1657, 1599, 1634]

Now with 3 nine-sided dice ...

$ die_results.py -n 3 -s 9 10_000
[14, 36, 84, 142, 201, 301, 407, 509, 618, 703, 762, 819, 830, 846, 754, 725, 594, 492, 420, 263, 189, 138, 96, 44, 13]

Display results in a histogram (using plotly) ...

$ die_results.py --graph -n 3 -s 9 10_000

histogram

With a single roll, the lowest possible total is 3 and the highest is 27, with the graph clearly illustrating that roll scores cluster towards the middle and taper off at the edges.

I can see adding argparse to all but the simplest of my command-line Python programs! At the very least, the included --help option returns a nice program description.

Source: die_results.py and die.py


» Later: Minimal Debian

« Earlier: #100DaysOfCode