Learn how to create command-line interfaces (CLIs) for your Python scripts and applications using the argparse module. This tutorial covers the fundamentals of argparse, from basic usage to more advanced features like subparsers and customization.

Beginner30 minutes

Step 1: Introduction to argparse

The argparse module in Python makes it easy to write command-line tools and utilities with user-friendly syntax and help output. It automatically handles parsing arguments and options from sys.argv.

In this step, we'll go over why you might want to use argparse and some basic usage examples.

import argparse

parser = argparse.ArgumentParser(description='A simple argument parser')
parser.add_argument('name', type=str, help='Name of person to greet')
args = parser.parse_args()

print(f'Hello, {args.name}!')

Practice Exercise

Create a command-line tool that takes a filename as an argument and prints the contents of that file to the console.

Show Solution
import argparse

parser = argparse.ArgumentParser(description='Print file contents')
parser.add_argument('filename', type=str, help='Name of file to read')
args = parser.parse_args()

with open(args.filename, 'r') as f:
    contents = f.read()
    print(contents)

Step 2: Positional and Optional Arguments

In argparse, arguments can be either positional or optional.

- Positional arguments are required arguments that must be provided in the correct order on the command line.

- Optional arguments are, well, optional. They are marked with a leading - or -- and can be provided in any order.

This step covers adding both types of arguments to your parser.

import argparse

parser = argparse.ArgumentParser()

# Positional argument
parser.add_argument('name', type=str, help='Name of person')

# Optional argument with shorthand -o
parser.add_argument('-o', '--occupation', type=str, help='Occupation')

args = parser.parse_args()

print(f'{args.name} is a {args.occupation}')

Practice Exercise

Build a command-line tool for a pizza restaurant that takes the size (positional arg) and optional toppings (-t/--toppings) and prints an order summary.

Show Solution
import argparse

parser = argparse.ArgumentParser(description='Pizza Order')
parser.add_argument('size', type=str, help='Size of pizza')
parser.add_argument('-t', '--toppings', nargs='+', help='List of toppings')

args = parser.parse_args()

print(f'You ordered a {args.size} pizza')

if args.toppings:
    toppings = ', '.join(args.toppings)
    print(f'With toppings: {toppings}')

Step 3: Argument Types and Nargs

argparse supports different data types for arguments using the type parameter. Common types include str, int, float, and file (for reading/writing files).

You can also specify nargs to control how many values an argument can accept.

- nargs='?': 0 or 1 value

- nargs='*': 0 or more values

- nargs='+': 1 or more values

- nargs=N: N values

This is useful for building flexible command-line tools.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('numbers', type=int, nargs='+', help='List of ints')
parser.add_argument('-f', '--file', type=argparse.FileType('w'), help='Output file')

args = parser.parse_args()

sum = 0
for n in args.numbers:
    sum += n
    
if args.file:
    args.file.write(str(sum))
else:
    print(sum)

Practice Exercise

Create a command-line calculator that accepts an operation (+, -, *, /) and a list of numbers. It should perform the operation on the numbers and print the result. Support outputting to a file with -o/--output.

Show Solution
import argparse
import operator

ops = {
    '+': operator.add,
    '-': operator.sub, 
    '*': operator.mul,
    '/': operator.truediv
}

parser = argparse.ArgumentParser(description='Command Line Calculator')
parser.add_argument('operation', choices=ops.keys(), type=str, help='Operation')
parser.add_argument('numbers', nargs='+', type=float, help='Numbers')
parser.add_argument('-o', '--output', type=argparse.FileType('w'), help='Output file')

args = parser.parse_args()

op_func = ops[args.operation]
result = args.numbers[0]

for num in args.numbers[1:]:
    result = op_func(result, num)
    
if args.output:
    args.output.write(str(result))
else:
    print(result)

Step 4: Customizing Help and Usage

Adding a description and customizing usage examples when running with -h/--help makes your CLI tools more user-friendly.

- description: Overall description of the tool's purpose

- usage: Example usage string

- epilog: Additional text after help output

You can also customize help strings for specific arguments using help.

This improves the tool's discoverability and ease of use.

import argparse

parser = argparse.ArgumentParser(
    prog='MYCLI',
    description='My useful command line tool',
    epilog='This is additional help text',
    usage='%(prog)s [options] path'
)

parser.add_argument('path', type=str, help='Path to operate on')
parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output')

args = parser.parse_args()

# Tool logic here

Practice Exercise

Create a command-line tool for a book library. Customize the help output with a description, usage example, and additional help text explaining the different file formats supported. Accept arguments for the library file (-f/--file) and an optional author to search for.

Show Solution
import argparse

parser = argparse.ArgumentParser(
    prog='BookLibrary',
    description='Command line tool for a book library',
    epilog='Supported file formats: csv, json, xml',  
    usage='%(prog)s -f file [--author AUTHOR]'
)

parser.add_argument('-f', '--file', required=True, help='Library file')
parser.add_argument('--author', help='Filter by author name')

args = parser.parse_args()

# Library code to load file, filter by author if provided, etc.

Step 5: Subparsers for Nested Commands

For complex command-line tools with nested sub-commands, argparse provides subparsers to separate concerns.

Each subparser manages its own arguments and options, creating a clean interface. The main parser routes to the appropriate subparser based on the sub-command.

This pattern helps manage growing complexity and promotes code reuse across sub-commands.

import argparse

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='command')

# Subparser for 'add' command
add_parser = subparsers.add_parser('add', help='Add numbers')
add_parser.add_argument('ints', nargs='+', type=int)

# Subparser for 'query' command 
query_parser = subparsers.add_parser('query', help='Query a database')
query_parser.add_argument('name', type=str, help='Entry name')

args = parser.parse_args()

if args.command == 'add':
    sum = 0
    for i in args.ints:
        sum += i
    print(sum)
elif args.command == 'query':
    # Query database logic

Practice Exercise

Extend the book library tool to include sub-commands for 'list' (print book titles), 'search' (search by author/title), and 'export' (export to a new file format).

Show Solution
import argparse

parser = argparse.ArgumentParser(prog='BookLibrary', description='Command line book library')
subparsers = parser.add_subparsers(dest='command')

# List subparser
list_parser = subparsers.add_parser('list', help='List books')

# Search subparser
search_parser = subparsers.add_parser('search', help='Search books') 
search_parser.add_argument('--author', help='Search by author')
search_parser.add_argument('--title', help='Search by title')

# Export subparser
export_parser = subparsers.add_parser('export', help='Export to file')
export_parser.add_argument('format', choices=['csv', 'json', 'xml'], help='Output format')
export_parser.add_argument('outfile', type=argparse.FileType('w'), help='Output file')

args = parser.parse_args()

# Load library data

if args.command == 'list':
    for book in library:
        print(book.title)
        
elif args.command == 'search':
    if args.author:
        # Search by author
    elif args.title:
        # Search by title
        
elif args.command == 'export':
    if args.format == 'csv':
        # Export to CSV
    elif args.format == 'json':
        # Export to JSON
    else:
        # Export to XML
        
    args.outfile.write(formatted_data)

Sign in to take Cornell notes on this lesson — they save automatically and stay with your account.

Sign in

Click to access the login or register cheese