Python command line interfaces: An overview of argparse.

Command-line or console applications are programs that are designed to be used via a text only interface such as the terminal. Command-line programs accept instructions or commands from their users in the form of flags or switches. Popular command-line applications include:

  • git – A version control system
  • Vim – A text editor and
  • Grep – A search utility

There are a number of Python modules designed for developing command-line interfaces. This post will focus on argparse, the module that comes standard with Python.

Argparse

Argparse allows you to make user-friendly interfaces and add arguments to your command-line applications easily. The benefit of using a module like argparse is that it allows parsing and validation of user input without having to write lots of code. argparse can also display appropriate messages when users enter incorrect input right out of the box.

In this article, I will introduce the most common argparse features and show you how to build a simple calendar application.

Getting Started

The first thing to do is to import argparse and create an ArgumentParser object.

import argparse

parser = argparse.ArgumentParser()
parser.parse_args()

The code we just wrote doesn’t do much, except initialise the parser object.
parser.parse_args() returns a Namespace object that contains key-value pairs of arguments and their values. parse_args requires a list of strings as it’s input and it takes it’s input from sys.argv by default.
Running the script with the --help option gives us the following output:

terra@shadow:/tmp$ python argparse_script.py --help
usage: argparse_script.py [-h]

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

argparse automatically adds a help flag or option to all instances of ArgumentParser(). As you can see, from writing only three lines of code, we now have very basic usage documentation that tells us the name of the script and what optional arguments are supported. Let’s add more to the usage documentation.

import argparse                                              
parser = argparse.ArgumentParser()

parser.prog = "Commandline Calendar"
parser.description = "A simple utility to display a calendar."
parser.epilog = "Full documentation available at http:www.example.com/"

That gives the script a Program name, and a description:

terra@shadow:/tmp$ python argparse_script.py --help
usage: Commandline Calendar [-h]

A simple utility to display a calendar .

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

Full documentation available at http:www.example.com/

Adding arguments

The power of argparse is in it’s ability to handle complex arguments. The calendar application we are building must be able to display the calendar of any month. In order to display the calendar of a given month, our program will need to know two things; the year and the month it must produce a calendar for. Let’s add additional code to add these two arguments.

Positional Arguments

argparse Supports two types of arguments:

  1. Positional arguments and
  2. Optional arguments

Positional arguments are required arguments and they should be entered in the correct order. Adding a positional argument to the parser is simple:

 parser.add_argument("foo", help="Help text for foo")

The code below, adds the month and year positional arguments.

import argparse
parser = argparse.ArgumentParser()

parser.prog = "Commandline Calendar"                                        
parser.description = "A simple utility to display a calendar."
parser.epilog = "Full documentation available at http:www.example.com/"
parser.add_argument("month", help="The month")
parser.add_argument("year", help="The year")
parser.parse_args()

The output:

terra@shadow:/tmp$ python argparse_script.py --help
usage: Commandline Calendar [-h] month year

A simple utility to display a calendar for the specified month.

positional arguments:
  month       The month
  year        The year

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

Full documentation available at http:www.example.com/

Running the program without any options or arguments generates an error that argparse handles:

terra@shadow:/tmp$ python argparse_script.py
usage: Commandline Calendar [-h] month year
Commandline Calendar: error: too few arguments

This is much better than having to code that functionality ourselves. At this point, running the script and supplying it with a month and year like this

terra@shadow:/tmp$ python argparse_script.py January 2017

does nothing because we have not written any logic to handle those options yet.

Optional arguments

Optional arguments are arguments that are usually preceded by a double dash “--” or a single dash “-“. These can include a short alias. An example of an optional argument is the help argument that is invoked by typing -h or --help.

The syntax for creating optional arguments is:

parser.add_argument('-b','--bar', help="bar help")

Let’s add an optional verbosity option to our calendar program.

import argparse                          
parser = argparse.ArgumentParser()

parser.prog = "Commandline Calendar"
parser.description = "A simple utility to display a calendar."
parser.epilog = "Full documentation available at http:www.example.com/"
parser.add_argument("month", help="The month")
parser.add_argument("year", help="The year")
parser.add_argument('-v','--verbose', help="Print calendar for the month", action="store_true")

parser.parse_args()

The action="store_true" part instructs the parser to set the Value of verbose to True if the --verbose or -v option is supplied.

In the first code sample, I mentioned that parser.parse_args() returns a Namespace object. This object is not unlike a Python dictionary. The Namespace object returned by the parse_args() method contains all the information received as arguments from the user. For our program to be useful, we must have a way to access the arguments our users will parse to the program. To do this, assign the return value of the parse_args() method to a variable:

args = parser.parse_args()

This will enable us to ‘read’ the arguments supplied by accessing them using dot notation like this: args.month, args.year or args.verbose

Our interface looks good now, we have two required arguments and one optional one:

terra@shadow:/tmp$ python argparse_script.py --help
usage: Commandline Calendar [-h] [-v] month year

A simple utility to display a calendar for the specified month.

positional arguments:
  month          The month
  year           The year

optional arguments:
  -h, --help     show this help message and exit
  -v, --verbose  Print calendar for the month

Full documentation available at http:www.example.com/

We have successfully created an interface using argparse that takes care of input validation. Now let’s finish off the calendar application. I have added extra functionality and renamed the script to month_cal.py.


import argparse
import calendar


def get_args():

    # Create a parser
    parser = argparse.ArgumentParser(
        prog="Calendar Utility",
        description="A simple utility to display a calendar for the specified month",
        epilog="Full documentation available at www.yoursite.com",
        usage="month_cal.py MONTH-NAME... YEAR...")
    
    # Positional arguments
    parser.add_argument(
        "month", help="The month")
    parser.add_argument(
        "year", type=int, help="The year")

    # Optional Argument
    parser.add_argument(
        "--verbose", "-v", help="Print out a calendar for the month.", action="store_true")
    args = parser.parse_args()
    return args


def main():
    args = get_args()
    month = args.month.capitalize()
    year = args.year

    # calendar requires month to be entered as an int
    months_list = dict((v, k) for k,v in enumerate(calendar.month_name))
    if args.verbose:
        try:
            calendar.prmonth(year, months_list[month])
        except KeyError:
            pass
    else:
        print("You entered %s %s") %(month, year)

if __name__ == '__main__':
    main()




Output without any verbosity.

terra@shadow:/tmp$ python month_cal.py October 2017
You entered October 2017

Output when verbosity is requested.

terra@shadow:/tmp$ python month_cal.py  October 2017 --verbose
    October 2017
Mo Tu We Th Fr Sa Su
                   1
 2  3  4  5  6  7  8
 9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31


There is a lot more to argparse that I did not cover here, such as handling conflicting options, creating argument groups and advanced argument handling. I recommend that you read more about it in the Python documentation. Thank you for reading.

2 comments on “Python command line interfaces: An overview of argparse.Add yours →

Leave a Reply