A short introduction to python parsers (part 2): ArgumentParser

Posted by Saugata Chatterjee on May 19, 2022 · 10 mins read

Use ArgumentParser module to add command line type argument parsing capabilities to python programs.

Argparser

Let’s start with an example.

countposts.py -h

usage: countposts.py [-h] [-v] [-o] [-a] [-s] [-g] [-t]

countposts.py: Count posts

optional arguments:
  -h, --help         show this help message and exit
  -v, --verbose      Verbose mode [Default=Off]
  -o, --headless     Headless mode [Default=Off]
  -a, --countall     Count posts for all [Default=Off]
  -s, --saveasyougo  Save data as the code runs [Default=Off]
  -g, --dash         Generate dash only [Default=Off]
  -t, --test         Test mode [Default=Off]

This is the output of countposts.py -h. We do not need to write any extra lines of code to display the help menu. It is automatically generated by the parser. All we need to do is add the arguments, and set the variable types and values they can take. While the possibilities are endless and a lot of complex arguments can be generated, we will focus on simple implementations. Almost always the simplest ones are sufficient. For a more in-depth discussion see the docs.

The code

The above output is generated by the following code.

import argparse

def getargs():
    # parse command-line arguments using argparse()
    description = """countposts.py: Count posts"""
    parser = argparse.ArgumentParser(description=description)
    parser.add_argument('-v', '--verbose', help='Verbose mode [Default=Off]', action='store_true')
    parser.add_argument('-o', '--headless', help='Headless mode [Default=Off]', action='store_true')
    parser.add_argument('-a', '--countall', help='Count posts for all [Default=Off]', action='store_true')
    parser.add_argument('-s', '--saveasyougo', help='Save data as the code runs [Default=Off]', action='store_true')
    parser.add_argument('-g', '--dash', help='Generate dash only [Default=Off]', action='store_true')
    parser.add_argument('-t', '--test', help='Test mode [Default=Off]', action='store_true')
    args = parser.parse_args()
    return args

def main():
    args = getargs()
    verbose = args.verbose
    testing = args.test
    saveasyougo = args.saveasyougo
    countall = args.countall
    headless = args.headless
    dash = args.dash
    
if __name__ == "__main__":
    main()    

Most of the lines are self-explanatory. All variables (arguments) are boolean and take True or False values. The default value is False. Let’s dissect the getargs() method.

parser = argparse.ArgumentParser(description=description)

This line creates the ArgumentParser instance and sets the description parameter. The description parameter describes the script (what it does). If we want to add a use case, we can use the epilog keyword.

parser.add_argument('-v', '--verbose', help='Verbose mode [Default=Off]', action='store_true')

This line adds a new argument. Both the short and long forms of the switch are defined. The verbose switch can be invoked either by the short-form -v switch or the long-form --verbose. These are also called options. As we will see below, ArgumentParser will return a namespace where the long-form argument names will be used as variables. The help keyword explains the argument (switch) does. It is good practice to specify the default values. The action keyword specifies what action is taken when the argument (switch) is invoked. action='store_true' informs ArgumentParser to store TRUE in the variable verbose.

To sum it up, ArgumentParser creates a variable named verbose and sets its type as Boolean. Then it stores FALSE as the default value. When this option is invoked in the command line by the user, ArgumentParser will change its value to TRUE.

The rest of the lines have identical functionality.

args = parser.parse_args()

This line collects all the values, packs them in a namepace, and returns them.

Let’s look at the main() method where these arguments are unpacked.

def main():
    args = getargs()
    verbose = args.verbose

The packed values are fetched into args. We can access individual variables by refering to the long-form names of the arguments.

How to add numerical arguments to ArgumentParser

We can easily extend the above implementation to add arguments which can take numerical values.

def getargs():
    # parse command-line arguments using argparse()
    description = """countposts.py: Count posts"""
    parser = argparse.ArgumentParser(description=description)
    parser.add_argument('-v', '--verbose', help='Verbose mode [Default=Off]', action='store_true')
    parser.add_argument('-o', '--headless', help='Headless mode [Default=Off]', action='store_true')
    parser.add_argument('-a', '--countall', help='Count posts for all [Default=Off]', action='store_true')
    parser.add_argument('-d', '--timedelta', help='Counts posts within [n] days [Default=0]', type=int)
    parser.add_argument('-s', '--saveasyougo', help='Save data as the code runs [Default=Off]', action='store_true')
    parser.add_argument('-g', '--dash', help='Generate dash only [Default=Off]', action='store_true')
    parser.add_argument('-t', '--test', help='Test mode [Default=Off]', action='store_true')
    args = parser.parse_args()
    return args

We have added an extra argument.

parser.add_argument('-d', '--timedelta', help='Counts posts within [n] days [Default=0]', type=int)

The type=int keyword tells ArgumentParser to treat the argument timedelta as an integer. If we now type countposts.py -h, we will get the following.

countposts.py -h

usage: countposts.py [-h] [-v] [-o] [-a] [-d TIMEDELTA] [-s] [-g] [-t]

countposts.py: Count posts

optional arguments:
  -h, --help         show this help message and exit
  -v, --verbose      Verbose mode [Default=Off]
  -o, --headless     Headless mode [Default=Off]
  -a, --countall     Count posts for all [Default=Off]
  -d TIMEDELTA, --timedelta TIMEDELTA
                        Counts posts within [n] days [Default=0]
  -s, --saveasyougo  Save data as the code runs [Default=Off]
  -g, --dash         Generate dash only [Default=Off]
  -t, --test         Test mode [Default=Off]

There so many other possibilities which we didn’t explore. Feel free to check out https://docs.python.org/3/library/argparse.html for more options.