Back to articles list Articles
11 minutes read

A Guide to the Python argparse Module

Want to write more professional, cleaner-looking code? Use the Python argparse module. This article will show you how to build a command line interface in Python with argparse.

In Python, argparse is one of those modules that can help you write more professional and better-looking Python code. This is because argparse makes it easy to write user-friendly command-line interfaces. By the end of this article, you will have acquired a solid knowledge of the argparse module – you can even use the article as your Python argparse cheat sheet.

Are you ready? Let’s get right into it!

In this guide, let's see if we can load an image using OpenCV from the command line.

OpenCV is a very popular computer vision library. It performs various tasks to process images, detect objects, etc. Here, we will use it to have some visual examples of running a script from the command line using the Python argparse module.

You can install OpenCV directly with pip:

pip install OpenCV-python  

Since we do not need to install Python argparse, we are good to go.

Feel free to choose an image of your choice as you follow this guide. I took a picture from Unsplash that I renamed 001.jpg to make it easy to work with. If you prefer to use Python to download a file directly, you can learn how to do it here. (By the way, check out my article on renaming files in Python if you want to learn how to do that easily.)

The Command Line Interface We’ll Build

First, let’s start with a script to either load an image or flip it around the x-axis in OpenCV. We want to run this from the command line. In a nutshell, our script will call the imread() and imshow() methods from OpenCV to read and display the image.

We will also add the option to call the flip() method from OpenCV to flip the image vertically.  It will be done with an if-else statement. If I use the --flip argument, the output will be the flipped image; otherwise, it will simply display the image.

I created a file named display_img_opencv.py with the following code:

import cv2
import argparse

# Construct the argument parser and parse the arguments
arg_desc = '''\
        Let's load an image from the command line!
        --------------------------------
            This program loads an image
            with OpenCV and Python argparse!
        '''
parser = argparse.ArgumentParser(formatter_class = argparse.RawDescriptionHelpFormatter,
                                    description= arg_desc)

parser.add_argument("-i", "--image", metavar="IMAGE", help = "Path to your input image")
parser.add_argument("-f", "--flip", metavar="IMAGE_FLIP", help = "Path to your input image")
args = vars(parser.parse_args())


if args["flip"]:
    # Flip the image vertically
    print("[INFO] flipping image vertically...")
    flipped = cv2.imread(args["flip"])
    flip_img = cv2.flip(flipped, 0)
   
    # Display the flipped image and press any key to stop
    cv2.imshow("Flipped vertically", flip_img)
   
else:
    # Load the image with "cv2.imread"
    image = cv2.imread(args["image"])
    # Display the original image
    cv2.imshow("Image", image)

cv2.waitKey(0)

Then, we can run the script with:

python display_img_opencv.py --image 001.jpg

And here is the result:

A Guide to the Python argparse Module

Or we can flip the image vertically with the following command line instruction:

python display_img_opencv.py --flip 001.jpg

As a result, our initial image has been flipped around the x-axis.

A Guide to the Python argparse Module

You can stop the script by pressing any key. Feel free to try it with your own image.

Now, let’s explain how to build the command-line interface with the Python argparse module.

Building a Command Line Interface With Python’s argparse

In this section, we will learn the step-by-step process to build a command-line interface with the Python argparse module.

Adding Script Description with argparse

The first step is to create an ArgumentParser object to hold all the information necessary to parse the command line into Python before setting the parser with the parse_args() method.

Note: Here, we need to wrap the parse_args() method with the vars() method to avoid an error. You can refer to the namespace section in Python’s documentation for further explanations.

Next, we also add a description to the ArgumentParser object to explain briefly what the program does.

The simplest way to do it is:

parser = argparse.ArgumentParser(description = "Load and flip an image with OpenCV")

Note: You might want to have a better-formatted description, depending on your needs.

In this case, I set my description string as a variable called arg_desc, and then I passed it into ArgumentParser().

Assigning argparse.RawDescriptionHelpFormatter to the formatter_class parameter allows me to format the description the way I want.

# Construct the argument parser and parse the arguments
arg_desc = '''\
        Let's load an image from the command line!
        --------------------------------
            This program loads an image
            with OpenCV and Python argparse!
        '''
parser = argparse.ArgumentParser(formatter_class = argparse.RawDescriptionHelpFormatter,
                                    description= arg_desc)

Positional Arguments in Python argparse

Next, we need to add a positional argument. In this case, we have two arguments, one to load our image and another one to flip it vertically:

parser.add_argument("-i", "--image", metavar="IMAGE", help = "Path to your input image")
parser.add_argument("-f", "--flip", metavar="IMAGE_FLIP", help = "Path to your input image")

I could also have written these lines of code as:

parser.add_argument("image", metavar="IMAGE", help = "Path to your input image")
parser.add_argument("flip", metavar="IMAGE_FLIP", help = "Path to your input image")

"image" and "flip" are called positional arguments and refer to the attribute action. By default, this is the first parameter of add_argument().

However, you can also provide optional arguments with a series of flags, as I did in the first script. These optional arguments are marked with - and -- as prefixes and provide some flexibility. They can replace a positional argument.

Accessing argparse Values

By default, ArgumentParser uses the dest value as the “name” of each object, but it is possible to provide an alternative name with metavar. However, note that it only changes the name displayed in help messages (in place of the dest value).

parser.add_argument("-i", "--image", metavar="IMAGE", help = "Path to your input image")
parser.add_argument("-f", "--flip", metavar="IMAGE_FLIP", help = "Path to your input image")

In this case, I set metavar as “IMAGE” for the first dest value and “IMAGE_FLIP” for the second one.

Adding Help

Next, we can set the help parameter to provide guidance on how to use our script. In this case, I set "Path to your input image". Now, when I run the following command-line instructions:

python display_img_opencv.py --help

I have the following output:

usage: display_img_opencv.py [-h] [-i IMAGE] [-f IMAGE_FLIP]                                                                                                                                                                                            Let's load an image from the command line!                                                                              --------------------------------                                                                                            This program loads an image                                                                                             with OpenCV and Python argparse!                                                                                                                                                                                                                                                                                                                            optional arguments:                                                                                                       -h, --help            show this help message and exit                                                                   -i IMAGE, --image IMAGE                                                                                                                       Path to your input image                                                                          -f IMAGE_FLIP, --flip IMAGE_FLIP                                                                                                              Path to your input image        

In the next section, we will explore how to switch the default value of a boolean flag.

Switching Default Values in argparse

Python supports two types of arguments: those with value and those without. For example, I can rewrite my positional argument with a default value – in this case, our image file 001.jpg.

parser.add_argument("-i", "--image", metavar="IMAGE", default="001.jpg", help = "Path to your input image")
parser.add_argument("-f", "--flip", metavar="IMAGE_FLIP", help = "Path to your input image")

Now, if I run the script as …

python display_img_opencv.py 

… it will display the image file 001.jpg.

A Guide to the Python argparse Module

It is also possible to have an argument without value. In this case, the argument either exists or not.

Let’s take another example. We want to display an image and get information about this image, such as its dimensions and number of channels. But we only want this info if --verbose is specified. Otherwise, the script will only display the image without returning any information about it.

import argparse
import cv2

# Construct the argument parser and parse the arguments
arg_desc = '''\
        Let's load an image from the command line!
        --------------------------------
            This program loads an image
            with OpenCV and Python argparse!
        '''

parser = argparse.ArgumentParser(formatter_class = argparse.RawDescriptionHelpFormatter,
                                    description= arg_desc)

parser.add_argument("-i", "--image", default="001.jpg", help = "Path to your input image")
parser.add_argument("-v", "--verbose", action="store_const", const=False, default=True, help = "Path to your input image")
args = vars(parser.parse_args())

# Load the image with "cv2.imread"
image = cv2.imread(args["image"])
# Dimensions, including width, height, and number of channels
(h, w, c) = image.shape[:3]

if args["verbose"]:
   
    # Display the image width, height, and number of channels   
    print("width: {} pixels".format(w))
    print("height: {}  pixels".format(h))
    print("channels: {}".format(c))

    # Display the image
    cv2.imshow("Image", image)
   
else:
   
    # Display the image
    cv2.imshow("Image", image)

cv2.waitKey(0)

The action="store_const" parameter means that the argument value is whatever is set in the const parameter when the argument is present. If the argument is not present, then it takes the value specified by the default parameter.

In the line above, the script will both display the image and the information related to it by default:

python load_img.py -i 001.jpg 
width: 640 pixels
height: 427  pixels
channels: 3

And the image:

A Guide to the Python argparse Module

We can also decide not to specify any default value. In this case, the default parameter will be None. In this example, our argument will become False:

parser.add_argument("-i", "--image", default="001.jpg", help = "Path to your input image")
parser.add_argument("-v", "--verbose", action="store_const", const=False, help = "Path to your input image")

Running the script will only display the image, without any information.

Now, you can see that the value of const and default are usually opposite in the case of  boolean arguments.

To make it easier to handle, Python has shortcut actions called store_true and store_false. The store_true is similar to const=True and default=False, while store_false is the opposite.

For example, I can get the information about the image by default by setting action=store_false. Below is the modified script:

parser.add_argument("-i", "--image", default="001.jpg", help = "Path to your input image")
parser.add_argument("-v", "--verbose", action="store_false", help = "Path to your input image")

Now, running the script will display the image as well as the information related to it.

If you want to turbocharge your Python skills, do not forget to check our Python programming track. It will help you to reach your goals faster.

Handling Incorrect Data

For some reason, you can enter invalid arguments as command line arguments. In this case, an error will kill the script. However, it is possible to run our script with only partially correct arguments.

One way of doing this is to add an argument with the nargs="*" parameter to accept any number of arguments and then add a dictionary of accepted values to parse_args() without dashes.

parser.add_argument("-i", "--image", default="001.jpg", help = "Path to your input image")
parser.add_argument("-v", "--verbose", action='store_false', help = "Path to your input image")
parser.add_argument("remainder", nargs="*")
args = vars(parser.parse_args(["v", "i", "image", "verbose"]))

This way, even if we enter incorrect dest values in the terminal, our script will still run. Here is an example:

python load_img.py world --cruel happy YEAH 
A Guide to the Python argparse Module

As explained earlier, the script ignores the unknown values and still works.

Note: Once you push your project to GitHub, do not forget to add the command-line instructions in your README.md file:

python display_img_opencv.py image 001.jpg 

If you are not familiar with GitHub, you can learn more about it in our article How to Start Working with GitHub.

Using argparse With Pathlib and JSON

Now, let’s talk about the type parameter. It is set as str by default, but you can change this value if needed.

In the example below, we set type=int because we want to calculate the cube value of an integer:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("cube", help="display a cube of a given number",
                    type=int)
args = parser.parse_args()
print(args.cube**3)
python math.py 5                                
125          

We can also use other class constructors as variable types. You can learn how to create Python classes here.

In the next example, we’ll combine Pathlib with argparse to change the directory from the command line.

import argparse
from pathlib import Path

parser = argparse.ArgumentParser()
parser.add_argument("--path", type=Path, default=Path(__file__).absolute().parent, help="Path to the target directory")

args = parser.parse_args()
print(args.path, type(args.path))

A command-line argument comes as a string; the type parameter will take a function that accepts a string and returns a value. Here, setting type=Path will convert the string to a Path object.

If you are curious about Pathlib, you can read more about it here.

Now, let's say you want to set a dictionary as an optional argument. You can do it using json.loads:

import json
import argparse

dict = '{"name": "img.jpg", "person": "Max", "flower": "tulip", "animal": "lion"}'

# Parse a dict
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--input', type=json.loads)
args = parser.parse_args(['-i', dict])
print(args.input)

This will return the following:

{'name': 'img.jpg', 'person': 'Max', 'flower': 'tulip', 'animal': 'lion'}

You can learn more about JSON here. If you do not know anything about working with JSON files in Python, I encourage you to join our course on How to Read and Write JSON Files in Python.

You can also use argparse to serialize any data class from/to JSON or YAML.

Last but not least, with Python argparse, you can add support for serializing/deserializing your own custom types. You can read more about building your own custom classes in Python here and serialization/deserialization in Python here.

Feel free to check the  Python argparse documentation for more details.

What Else Can You Do with the Python argparse Module?

In this guide to the Python argparse module, we learned how to add a command line interface to our Python script. I highly encourage you to play around with the code and add it to your projects. It will contribute a lot of value, and it does not cost much.

Want to learn more about Python programming? Check out my article about writing better Python code for more tips. We have lots of other articles at LearnPython.com that cover a variety of subjects, too.