Arguments: Your Script Becomes a Tool
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.
import sys
print(sys.argv)
['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.
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")
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.
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.
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.
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)
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.
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')
- "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.
- 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