How to Use the Argparse Module in Python

Master the argparse module in Python with this comprehensive tutorial, covering command-line applications, argument parsing, real-world examples, integration with other libraries, and best practices to create user-friendly interfaces and powerful command-line tools.
  · · 13 min read · Updated apr 2023 · Python Standard Library

Step up your coding game with AI-powered Code Explainer. Get insights like never before!

Introduction

Argparse is a powerful built-in Python module designed to create user-friendly command-line interfaces. In this comprehensive guide, you learn how to effectively use argparse for your command-line applications. We will cover the basics, delve into advanced features, and explore best practices to create polished and efficient command-line tools.

Table of Contents

  1. Getting Started with Argparse
  2. Advanced Argument Customization
  3. Subcommands and Complex Applications
  4. Real-world Argparse Applications
  5. Tips, Tricks, and Best Practices

1. Getting Started with Argparse

1.1 Importing Argparse

To begin using argparse, we need to import the module. Since it is a built-in module, no installation is required. Simply add the following line at the beginning of your Python script:

import argparse

1.2 Creating an ArgumentParser Object

To create a new ArgumentParser object, call the argparse.ArgumentParser() constructor. This object will be used to define and parse command-line arguments:

parser = argparse.ArgumentParser()

1.3 Adding Basic Arguments

To add arguments to the parser, use the add_argument() method. The first argument is the name of the command-line argument. The help parameter provides a brief description of the argument, which will be displayed when the user runs the program with the -h or --help flag:

parser.add_argument('input', help='Input file to process.')

1.4 Parsing Arguments and Displaying Results

To parse the command-line arguments, call the parse_args() method on the parser object. This method returns a namespace object, which can be used to access the values of the parsed arguments:

args = parser.parse_args()
print(args.input)

1.5 A Simple Argparse Example

Here's a complete example that demonstrates basic argparse usage:

import argparse

parser = argparse.ArgumentParser(description='A simple argparse example.')
parser.add_argument('input', help='Input file to process.')

args = parser.parse_args()
print(f'Processing file: {args.input}')

In the above example, I'm adding an example of an input file. You don't have to specify the argument name when passing it to this script, you can run it using the following:

$ python 1_simple_example.py input.txt
Processing file: input.txt

2. Advanced Argument Customization

2.1 Positional and Optional Arguments

Argparse supports two types of arguments: positional and optional. Positional arguments are required and are identified based on their position in the command-line invocation, like the input argument we added in the previous section.

Optional arguments, often referred to as "flags" or "switches," are identified by a preceding hyphen - or double hyphen --.

To create an optional argument, use the add_argument() method with a hyphen-prefixed string as the first argument:

parser.add_argument('-o', '--output', help='Output file.')

2.2 Default Values and Required Arguments

Optional arguments can be assigned a default value using the default parameter. If the user does not provide a value for the optional argument, the default value will be used:

parser.add_argument('-o', '--output', default='output.txt', help='Output file.')

To make an optional argument required, set the required parameter to True:

parser.add_argument('-o', '--output', required=True, help='Output file.')

To wrap up, here's the complete code so far:

import argparse

parser = argparse.ArgumentParser(description='A simple argparse example.')
parser.add_argument('input', help='Input file to process.')
# parser.add_argument('-o', '--output', default='output.txt', help='Output file.')
parser.add_argument('-o', '--output', required=True, help='Output file.')

args = parser.parse_args()
print(f'Processing file: {args.input}')
print(f"Writing to file: {args.output}")

In this case, I'm setting the output to be required. Let's try to forget it:

$ python 2_default_and_required.py input.txt
usage: 2_default_and_required.py [-h] -o OUTPUT input
2_default_and_required.py: error: the following arguments are required: -o/--output

As you can see, the parse_args() prevents the code from continuing executing as the -o/--output argument is missing and it's required, let's pass it now:

$ python 2_default_and_required.py input.txt -o output.txt
Processing file: input.txt
Writing to file: output.txt

2.3 Choices and Constraints

You can limit the accepted values for an argument using the choices parameter. This creates a constraint that only allows specified values for that argument:

parser.add_argument('-m', '--mode', choices=['add', 'subtract', 'multiply', 'divide'], help='Calculation mode.')

2.4 Argument Groups

Argument groups can be used to organize related arguments and display them together in the help message. To create an argument group, call the add_argument_group() method on the parser object:

group = parser.add_argument_group('authentication')

Then, add arguments to the group using the add_argument() method:

group.add_argument('-u', '--username', help='Username for authentication.')
group.add_argument('-p', '--password', help='Password for authentication.')

2.5 Nargs Argument: Specifying the Number of Command-Line Arguments

The nargs argument in argparse is used to specify the number of command-line arguments that should be consumed by a particular argument. By setting the nargs value, you can control how many values should be provided for a given argument. Here are the possible values for nargs:

  1. An integer (e.g., nargs=3): Specifies that exactly this many values should be consumed. If the required number of values is not provided, argparse raises an error.
    parser.add_argument('--values', nargs=3)
    Command-line usage:
    $ python 2.5_nargs.py --values 1 2 3
  2. "?": Specifies that the argument is optional, and it consumes one value if provided. If the argument is not present, the default value is used.
    parser.add_argument('--value', nargs='?', default='default_value')
    Command-line usage:
    $ python 2.5_nargs.py --value 42
    or:
    $ python 2.5_nargs.py
  3. "*": Specifies that the argument can consume zero or more values. If the argument is not present, an empty list is used.
    parser.add_argument('--values', nargs='*')
    Command-line usage:
    $ python 2.5_nargs.py --values 1 2 3
    or:
    $ python 2.5_nargs.py
  4. "+": Specifies that the argument can consume one or more values. If the argument is absent or no values are provided, argparse raises an error.
    parser.add_argument('--values', nargs='+')
    Command-line usage:
    $ python 2.5_nargs.py --values 1 2 3
    or:
    $ python 2.5_nargs.py --values 1​

In summary, the nargs argument in argparse is a powerful way to control the number of values expected for a specific command-line argument, enabling you to create flexible and user-friendly interfaces for your command-line applications.

2.6 Custom Argument Actions

Argparse provides several built-in actions for handling command-line arguments. In this section, we'll explore these built-in actions and show how to create custom argument actions using the __call__() method.

Built-in Actions:

1. "store" (default action): Store the value of the argument.

parser.add_argument('--foo', action='store', help='Store the value of foo.')

2. "store_true": Store the value True if the argument is present, False otherwise.

parser.add_argument('--enable', action='store_true', help='Enable the feature.')

Command-line usage:

$ python script.py --enable

3. "store_false": Store the value False if the argument is present, True otherwise.

parser.add_argument('--disable', action='store_false', help='Disable the feature.')

Command-line usage:

$ python script.py --disable

4. "store_const": Store a constant value when the argument is present.

parser.add_argument('--level', action='store_const', const='advanced', help='Set level to advanced.')

Command-line usage:

$ python script.py --level

5. "append": Store multiple values for the same argument in a list.

parser.add_argument('--values', action='append', help='Append values to a list.')
args = parser.parse_args()
print(f"Values: {args.values}")

Command-line usage, the output of values will be a list:

$ python 2.6_builtin_actions.py --values 1 --values 2 --values 3                        
Values: ['1', '2', '3']

6. "append_const": Store a constant value in a list when the argument is present.

parser.add_argument('--add_const', action='append_const', const=42, help='Add 42 to the list.')

Command-line usage:

$ python script.py --add_const

7. "count": Count the number of occurrences of the argument.

parser.add_argument('-v', '--verbose', action='count', help='Increase verbosity level.')

Command-line usage:

$ python 2.6_builtin_actions.py --verbose --verbose
...
Verbosity: 2

Or using the -v flag:

$ python 2.6_builtin_actions.py -vvvv
...
Verbosity: 4

Argparse also allows us to make custom argument actions. Here's an example of an action that uppercase all the passed elements:

import argparse

class CustomAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        # Perform custom processing on the argument values
        processed_values = [value.upper() for value in values]

        # Set the attribute on the namespace object
        setattr(namespace, self.dest, processed_values)

# Set up argument parser and add the custom action
parser = argparse.ArgumentParser(description='Custom argument action example.')
parser.add_argument('-n', '--names', nargs='+', action=CustomAction, help='A list of names to be processed.')

args = parser.parse_args()
print(args.names)

Command-line usage:

$ python 2.6_custom_actions.py -n alice BoB Charlie
['ALICE', 'BOB', 'CHARLIE']

2.7 Specifying Argument Types

You can use built-in types such as int, str, or float to only accept these types of a certain parameter:

import argparse

parser = argparse.ArgumentParser(description='A simple argparse example.')
parser.add_argument("-r", "--ratio", type=float)
args = parser.parse_args()
print(f"Ratio: {args.ratio}")

Let's try to pass --ratio but with non-float:

$ python 2.7_argument_types.py -r hi
usage: 2.7_argument_types.py [-h] [-r RATIO]
2.7_argument_types.py: error: argument -r/--ratio: invalid float value: 'hi'

Now let's pass a float:

$ python 2.7_argument_types.py -r 5.3
Ratio: 5.3

Good! You can also pass an integer, say 5, and it'll be parsed as a 5.0 float.

You can also define custom argument types by creating a function that processes the input value and returns the processed result. Pass this function to the type parameter of the add_argument() method:

def custom_type(value):
    # Perform custom processing on the value
    return processed_value

parser.add_argument('-t', '--type', type=custom_type, help='Custom type example.')

2.8 Handling Errors and Exceptions

Argparse raises an argparse.ArgumentError exception when it encounters an error while parsing arguments. To gracefully handle these errors, you can catch the exception and display a custom error message:

try:
    args = parser.parse_args()
except argparse.ArgumentError as error:
    parser.error(str(error))

3. Subcommands and Complex Applications

3.1 Creating Subcommands

Subcommands allow you to create complex command-line applications with multiple actions. To create subcommands, first, add a subparsers object to your ArgumentParser:

subparsers = parser.add_subparsers(help='Subcommand help')

3.2 Managing Subcommands with add_subparsers()

Create a sub parser for each subcommand by calling the add_parser() method on the subparsers object:

subparser1 = subparsers.add_parser('subcommand1', help='Subcommand 1 help')
subparser2 = subparsers.add_parser('subcommand2', help='Subcommand 2 help')

3.3 Subcommand Examples

Here's an example of a command-line application that has two subcommands, list and add:

import argparse

parser = argparse.ArgumentParser(description='A subcommand example.')
subparsers = parser.add_subparsers(help='Subcommand help')

list_parser = subparsers.add_parser('list', help='List items')
add_parser = subparsers.add_parser('add', help='Add an item')
add_parser.add_argument('item', help='Item to add')

args = parser.parse_args()

3.4 Best Practices for Subcommands

  • Keep subcommands simple and focused on a single task.
  • Provide clear and concise help messages for each subcommand.
  • Use consistent naming conventions and argument syntax across all subcommands.

4. Real-world Argparse Applications

4.1 Building a File Renaming Tool

Using argparse, you can create a command-line tool for batch-renaming files based on user-defined rules:

import argparse
import os

# Rename function
def rename_files(args):
    # Your file renaming logic here
    print(f"Renaming files in {args.path}...")
    print(f"Prefix: {args.prefix}")
    print(f"Suffix: {args.suffix}")
    print(f"Replace: {args.replace}")
    os.chdir(args.path)
    for file in os.listdir():
        # Get the file name and extension
        file_name, file_ext = os.path.splitext(file)
        # Add prefix
        if args.prefix:
            file_name = f"{args.prefix}{file_name}"
        # Add suffix
        if args.suffix:
            file_name = f"{file_name}{args.suffix}"
        # Replace substring
        if args.replace:
            file_name = file_name.replace(args.replace[0], args.replace[1])
        # Rename the file
        print(f"Renaming {file} to {file_name}{file_ext}")
        os.rename(file, f"{file_name}{file_ext}")
        
# custom type for checking if a path exists
def path_exists(path):
    if os.path.exists(path):
        return path
    else:
        raise argparse.ArgumentTypeError(f"Path {path} does not exist.")
    
    
# Set up argument parser
parser = argparse.ArgumentParser(description='File renaming tool.')
parser.add_argument('path', type=path_exists, help='Path to the folder containing the files to rename.')
parser.add_argument('-p', '--prefix', help='Add a prefix to each file name.')
parser.add_argument('-s', '--suffix', help='Add a suffix to each file name.')
parser.add_argument('-r', '--replace', nargs=2, help='Replace a substring in each file name. Usage: -r old_string new_string')

args = parser.parse_args()

# Call the renaming function
rename_files(args)

In this example, we have built a file renaming tool, where you can pass a path, and it renames all the files inside that path using a prefix, suffix, or replace part of the file name. We have used the following:

  • Defining a custom type that verifies whether a string passed is an actual path in the local machine.
  • Leveraging the nargs parameter to replace a string from an old string to a new one.
  • Raising an ArgumentTypeError if a path passed does not exist.

Let's try to pass a path that does not exist:

$ python 4_file_renamer.py datarzerze -s "_text" 
usage: 4_file_renamer.py [-h] [-p PREFIX] [-s SUFFIX] [-r REPLACE REPLACE] path
4_file_renamer.py: error: argument path: Path datarzerze does not exist.

Clearly, the error is raised. Now let's pass a path that does exist and add a suffix of "_text" to all files inside:

$ python 4_file_renamer.py data -s "_text"     
Renaming files in data...
Prefix: None
Suffix: _text
Replace: None
Renaming item1.txt to item1_text.txt
Renaming item2.txt to item2_text.txt

4.2 Creating a Command-Line Calculator

A command-line calculator can be implemented with argparse by defining the mathematical operations as subcommands:

import argparse

# Operation functions
def add(args):
    print(args.x + args.y)

def subtract(args):
    print(args.x - args.y)

def multiply(args):
    print(args.x * args.y)

def divide(args):
    print(args.x / args.y)

# Set up argument parser
parser = argparse.ArgumentParser(description='Command-line calculator.')
subparsers = parser.add_subparsers()

# Add subcommands
add_parser = subparsers.add_parser('add', help='Add two numbers.')
add_parser.add_argument('x', type=float, help='First number.')
add_parser.add_argument('y', type=float, help='Second number.')
add_parser.set_defaults(func=add)

subtract_parser = subparsers.add_parser('subtract', help='Subtract two numbers.')
subtract_parser.add_argument('x', type=float, help='First number.')
subtract_parser.add_argument('y', type=float, help='Second number.')
subtract_parser.set_defaults(func=subtract)

multiply_parser = subparsers.add_parser('multiply', help='Multiply two numbers.')
multiply_parser.add_argument('x', type=float, help='First number.')
multiply_parser.add_argument('y', type=float, help='Second number.')
multiply_parser.set_defaults(func=multiply)

divide_parser = subparsers.add_parser('divide', help='Divide two numbers.')
divide_parser.add_argument('x', type=float, help='First number.')
divide_parser.add_argument('y', type=float, help='Second number.')
divide_parser.set_defaults(func=divide)

args = parser.parse_args()
args.func(args)

Let's run it:

$ python 4_simple_calculator.py --help
usage: 4_simple_calculator.py [-h] {add,subtract,multiply,divide} ...

Command-line calculator.

positional arguments:
  {add,subtract,multiply,divide}
    add                 Add two numbers.
    subtract            Subtract two numbers.
    multiply            Multiply two numbers.
    divide              Divide two numbers.

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


$ python 4_simple_calculator.py add 5 3
8.0
$ python 4_simple_calculator.py divide 90 5
18.0
$ python 4_simple_calculator.py multiply 42 19
798.0
$ python 4_simple_calculator.py subtract 10.5 3.2
7.3

Related: How to Make a Calculator with Tkinter in Python.

5. Tips, Tricks, and Best Practices

5.1 Click, Fire, and Other Command-Line Libraries

While argparse is a powerful library for building command-line applications, other alternatives like Click and Fire provide additional features and a different approach to argument parsing:

  • Click: a library that simplifies the process of creating complex command-line applications by using decorators.
  • Fire: an automatic command-line tool generator that inspects your functions and classes to create a CLI interface.

5.2 Writing Clean and Modular Code

When using argparse, it's essential to write clean, modular code by separating argument parsing, input validation, and application logic into separate functions or classes. This will make your code easier to read, understand, and maintain.

Also, you should design command-line interfaces that are user-friendly and intuitive. Provide clear and concise help messages, use consistent naming conventions, and follow established command-line conventions, such as using - for short options and -- for long options.

Conclusion

Finally, refer to the official Python argparse documentation for a complete reference of the library's features and usage. 

You can get most of the code snippets of this tutorial here.

Learn also: How to Get the Size of Directories in Python.

Happy coding ♥

Just finished the article? Now, boost your next project with our Python Code Generator. Discover a faster, smarter way to code.

View Full Code Auto-Generate My Code
Sharing is caring!



Read Also



Comment panel

    Got a coding query or need some guidance before you comment? Check out our Python Code Assistant for expert advice and handy tips. It's like having a coding tutor right in your fingertips!