CodingNic

Debugging, Testing, and Modules

Command-Line Arguments

Debugging, Testing, and Modules 20 min read

Command-Line Arguments

Objectives

By the end of this chapter, you should be able to:

  • Read arguments passed to a script with sys.argv
  • Define named, documented arguments with argparse

💡 Why this matters: Every script so far either hardcodes its input or calls input() mid-run. Real command-line tools take their input up front, when you launch them (git commit -m "message", python3 script.py --verbose), which is what actually makes a script reusable as a tool instead of a one-off.

sys.argv

Every value typed after python3 script.py on the command line is available inside your script as a list, sys.argv. The first element is always the script’s own filename:

python
# greet.py
import sys

print(sys.argv)
bash
python3 greet.py Erin Jordan
# ['greet.py', 'Erin', 'Jordan']
python
# greet.py
import sys

name = sys.argv[1]
print(f"Hello, {name}!")
bash
python3 greet.py Erin
# Hello, Erin!

sys.argv works, but it has real limits: every argument is a plain string (you’ll need to convert numbers yourself), there’s no built-in way to document what each argument means, and forgetting one raises a plain IndexError rather than a helpful message.

argparse

The argparse module, part of the standard library, solves all three problems. You declare each argument you expect, and it handles parsing, type conversion, defaults, and a free --help message:

python
import argparse

parser = argparse.ArgumentParser(description="Greet someone by name.")
parser.add_argument("name", help="the name to greet")
parser.add_argument("--times", type=int, default=1, help="how many times to repeat the greeting")

args = parser.parse_args()

for _ in range(args.times):
    print(f"Hello, {args.name}!")
bash
python3 greet.py Jordan
# Hello, Jordan!

python3 greet.py Jordan --times 3
# Hello, Jordan!
# Hello, Jordan!
# Hello, Jordan!

python3 greet.py --help
# usage: greet.py [-h] [--times TIMES] name
# ...

A few things worth noticing: name (no leading dashes) is a positional argument, required and matched by position. --times is an optional argument: the user can omit it, in which case it falls back to default=1. type=int converts the raw string "3" into the actual integer 3 before your code ever sees it, and --help is generated for you automatically from the help= text you provided.

Try It

  1. Write a script that reads a single value from sys.argv and prints something using it.
  2. Rewrite that script using argparse with one required positional argument, and run python3 yourscript.py --help to see the message it generates for free.
  3. Add an optional argparse argument with a default value and type=int, and confirm it converts correctly.

Recap

  • sys.argv is a plain list of the strings passed on the command line: simple, but every value is a string and there’s no built-in validation or help text.
  • argparse declares each expected argument up front, handling type conversion, defaults, and a --help message automatically.
  • Positional arguments (name) are required and matched by position; optional arguments (--times) can be skipped in favor of a default.

Next lesson: put debugging, testing, and modules into practice with a set of exercises.