Topic 05

Arguments: Your Script Becomes a Tool

Hands-on

A script that asks its questions with input has to be sat beside every time it runs. A tool takes its instructions on the command line instead: python wordcount.py notes.txt --lines, typed once, and it runs without asking anything. That means it can be repeated, scheduled, and combined with other programs. argparse, from the standard library, reads those instructions properly and writes the help text for you.

Think of the difference between a kitchen appliance that asks you questions every time you switch it on and one with clearly labelled buttons. The buttons are faster, you can press the same ones every morning, and anyone can see what they do.

Arguments

The words typed after the script's name are its arguments. Python makes them available in sys.argv, a list whose first item is the script's own name. That is enough for one simple argument; beyond that, checking what was given, reporting mistakes and explaining the options all by hand gets messy quickly.

args.py
import sys

print(sys.argv)
Running python3 args.py notes.txt --lines
['args.py', 'notes.txt', '--lines']

argparse

With argparse you declare the arguments your tool takes, and it does the rest. The word-count tool below has one required argument, the file, and one optional flag, --lines. parse_args reads the command line and gives back an object where each argument is available by name, as args.file and args.lines.

wordcount.py
import argparse
from pathlib import Path

parser = argparse.ArgumentParser(description="Count the words in a text file.")
parser.add_argument("file", help="the text file to count")
parser.add_argument("--lines", action="store_true", help="also count the lines")
args = parser.parse_args()

text = Path(args.file).read_text(encoding="utf-8")
print(f"{len(text.split())} words")
if args.lines:
    print(f"{len(text.splitlines())} lines")
Running it on notes.txt, with and without the flag
you@mac python-course % python3 wordcount.py notes.txt
8 words
you@mac python-course % python3 wordcount.py notes.txt --lines
8 words
3 lines

action="store_true" makes --lines a switch: present means True, absent means False. Forget the required file, and argparse refuses with a usage line and a clear error, and exits with the code 2, before your own code runs at all.

Forgetting the file
you@mac python-course % python3 wordcount.py
usage: wordcount.py [-h] [--lines] file
wordcount.py: error: the following arguments are required: file

help for Free

Every argparse tool understands --help, or -h, without you writing a line of help text. The description and the help strings you gave to each argument are laid out automatically, with the usage line at the top. In a terminal that supports colour, Python 3.15 also colours it.

python3 wordcount.py --help
usage: wordcount.py [-h] [--lines] file

Count the words in a text file.

positional arguments:
  file        the text file to count

options:
  -h, --help  show this help message and exit
  --lines     also count the lines

Options with Values, and Subcommands

An option can carry a value, such as --currency EUR, with a default for when it is left out. And a tool that does several related jobs can have subcommands, the way pip has pip install and pip list: one program, several actions, each with its own arguments. The skeleton below sets up the two commands of the expenses tool that Chapter 12 completes: summary, which totals a statement, and convert, which converts an amount. For now it just prints what argparse understood.

expenses.py
import argparse

parser = argparse.ArgumentParser(description="Look at your spending.")
commands = parser.add_subparsers(dest="command", required=True)

summary = commands.add_parser("summary", help="total a bank statement")
summary.add_argument("statement", help="the CSV file exported by your bank")

convert = commands.add_parser("convert", help="convert an amount to dollars")
convert.add_argument("amount", help="the amount, such as 86.40")
convert.add_argument("--currency", default="EUR", help="the currency it was paid in")

args = parser.parse_args()
print(args)
Three ways to run it
you@mac python-course % python3 expenses.py convert 86.40
Namespace(command='convert', amount='86.40', currency='EUR')
you@mac python-course % python3 expenses.py summary statement.csv
Namespace(command='summary', statement='statement.csv')
you@mac python-course % python3 expenses.py report
usage: expenses.py [-h] {summary,convert} ...
expenses.py: error: argument command: invalid choice: 'report' (choose from 'summary', 'convert')

The printed Namespace shows exactly what the program received: which command, and each argument by name. The amount is still text, '86.40', as everything from outside is; the program will turn it into a Decimal before using it. And the third run shows argparse refusing an unknown command, listing the ones that exist. A near miss gets more help: from Python 3.15, typing sumary, one letter short of summary, makes argparse ask whether you meant summary.

A mistyped command
you@mac python-course % python3 expenses.py sumary statement.csv
usage: expenses.py [-h] {summary,convert} ...
expenses.py: error: argument command: invalid choice: 'sumary', maybe you meant 'summary'? (choose from 'summary', 'convert')
One command line, taken apart
python3
the program to start
expenses.py
the script, sys.argv[0]
convert
the subcommand, args.command
86.40
a positional argument, args.amount (as text)
--currency EUR
an option with a value, args.currency
Common Confusions
  • "sys.argv is all I need." It is fine for one argument. Beyond that, argparse checks the input, reports mistakes and writes the help for you.
  • "Options must come in a fixed order." Named options can be given in any order; only the positional arguments depend on their position.
  • "Help text has to be written and kept up to date separately." argparse builds it from the declarations, so it cannot drift away from what the tool accepts.
Why It Matters
  • A script that runs without questions can be repeated, scheduled and combined with other tools, which is where scripts start saving real time.
  • A readable --help makes your tool usable by someone who has never seen its code, including you, a year from now.

Knowledge Check

What is sys.argv[0]?

  • The name of the script itself, args.py
  • The first argument typed after the script's name
  • The number of arguments that were given to it
  • The name of the Python program that was started

What does action="store_true" do for --lines?

  • It requires a value after --lines, such as a number
  • It stores the lines of the file in args.lines
  • It makes --lines a switch: True if given, False if not
  • It makes --lines a required argument that must always be typed

What happens when the required file argument is missing?

  • The program still runs, and counts zero words
  • Python raises a KeyError when it reads args.file
  • The program asks for the missing file with input, then carries on
  • argparse prints the usage and an error, then exits

What does python3 expenses.py convert 86.40 give as args.amount?

  • The text '86.40', still a string
  • The Decimal value 86.40, ready for sums
  • The float 86.4, a plain number
  • The subcommand's name, which is convert

You got correct