Skip to content

Python argparse & sys.argv — CLI Arguments

When you run a script from the terminal, the words after the script name are command-line arguments. Python gives you two ways to read them: the raw sys.argvsys.argv list, and the full-featured argparseargparse library.

run_example.py
# $ python greet.py Ada --times 3
import sys
print(sys.argv)   # ['greet.py', 'Ada', '--times', '3']
run_example.py
# $ python greet.py Ada --times 3
import sys
print(sys.argv)   # ['greet.py', 'Ada', '--times', '3']

sys.argv — the raw list

sys.argvsys.argv is a list of strings. The first item is always the script name; the rest are the arguments, as strings.

sys_argv.py
import sys
 
# $ python add.py 3 4
if len(sys.argv) != 3:
    print("Usage: python add.py NUM NUM")
    sys.exit(1)
 
a = int(sys.argv[1])    # convert from string!
b = int(sys.argv[2])
print(a + b)            # 7
sys_argv.py
import sys
 
# $ python add.py 3 4
if len(sys.argv) != 3:
    print("Usage: python add.py NUM NUM")
    sys.exit(1)
 
a = int(sys.argv[1])    # convert from string!
b = int(sys.argv[2])
print(a + b)            # 7

sys.argvsys.argv is fine for one or two arguments, but it forces you to handle conversion, validation, defaults, and help text by hand. For anything real, use argparseargparse.

argparse — the proper way

argparseargparse parses arguments, converts types, generates --help--help, and reports errors automatically.

argparse_basic.py
import argparse
 
parser = argparse.ArgumentParser(description="Greet someone.")
parser.add_argument("name", help="who to greet")
parser.add_argument("--times", type=int, default=1, help="how many times")
 
args = parser.parse_args()           # reads from sys.argv
for _ in range(args.times):
    print(f"Hello, {args.name}!")
argparse_basic.py
import argparse
 
parser = argparse.ArgumentParser(description="Greet someone.")
parser.add_argument("name", help="who to greet")
parser.add_argument("--times", type=int, default=1, help="how many times")
 
args = parser.parse_args()           # reads from sys.argv
for _ in range(args.times):
    print(f"Hello, {args.name}!")

Running it:

terminal
$ python greet.py Ada --times 2
Hello, Ada!
Hello, Ada!
 
$ python greet.py --help
usage: greet.py [-h] [--times TIMES] name
...
terminal
$ python greet.py Ada --times 2
Hello, Ada!
Hello, Ada!
 
$ python greet.py --help
usage: greet.py [-h] [--times TIMES] name
...

Positional vs optional arguments

KindDefined asExample
Positionaladd_argument("name")add_argument("name")python app.py Adapython app.py Ada
Optionaladd_argument("--times")add_argument("--times")python app.py --times 3python app.py --times 3
Flagadd_argument("--verbose", action="store_true")add_argument("--verbose", action="store_true")python app.py --verbosepython app.py --verbose
positional_optional.py
import argparse
 
parser = argparse.ArgumentParser()
parser.add_argument("filename")                      # required positional
parser.add_argument("--limit", type=int, default=10) # optional with default
parser.add_argument("--verbose", action="store_true")# flag -> True/False
 
# parse_args can take an explicit list (handy for testing)
args = parser.parse_args(["data.txt", "--limit", "5", "--verbose"])
print(args.filename)   # data.txt
print(args.limit)      # 5
print(args.verbose)    # True
positional_optional.py
import argparse
 
parser = argparse.ArgumentParser()
parser.add_argument("filename")                      # required positional
parser.add_argument("--limit", type=int, default=10) # optional with default
parser.add_argument("--verbose", action="store_true")# flag -> True/False
 
# parse_args can take an explicit list (handy for testing)
args = parser.parse_args(["data.txt", "--limit", "5", "--verbose"])
print(args.filename)   # data.txt
print(args.limit)      # 5
print(args.verbose)    # True

Tip: parse_args()parse_args() reads sys.argvsys.argv by default, but you can pass a list — parse_args(["a", "b"])parse_args(["a", "b"]) — which is perfect for tests and examples.

Useful add_argument options

OptionEffect
type=inttype=intConvert the value (to int, float, etc.).
default=...default=...Value used when the argument is omitted.
required=Truerequired=TrueMake an optional argument mandatory.
choices=[...]choices=[...]Restrict to a fixed set of values.
action="store_true"action="store_true"Boolean flag (no value needed).
nargs="+"nargs="+"Accept multiple values into a list.
help="..."help="..."Text shown in --help--help.
advanced.py
import argparse
 
parser = argparse.ArgumentParser()
parser.add_argument("--mode", choices=["fast", "safe"], default="safe")
parser.add_argument("--files", nargs="+")   # one or more values
args = parser.parse_args(["--mode", "fast", "--files", "a.txt", "b.txt"])
print(args.mode)    # fast
print(args.files)   # ['a.txt', 'b.txt']
advanced.py
import argparse
 
parser = argparse.ArgumentParser()
parser.add_argument("--mode", choices=["fast", "safe"], default="safe")
parser.add_argument("--files", nargs="+")   # one or more values
args = parser.parse_args(["--mode", "fast", "--files", "a.txt", "b.txt"])
print(args.mode)    # fast
print(args.files)   # ['a.txt', 'b.txt']

Short flags

Add a one-letter alias alongside the long name:

short_flags.py
import argparse
 
parser = argparse.ArgumentParser()
parser.add_argument("-n", "--number", type=int, default=1)
args = parser.parse_args(["-n", "7"])
print(args.number)   # 7
short_flags.py
import argparse
 
parser = argparse.ArgumentParser()
parser.add_argument("-n", "--number", type=int, default=1)
args = parser.parse_args(["-n", "7"])
print(args.number)   # 7

Common pitfalls

  • sys.argvsys.argv values are strings — convert with int()int()/float()float().
  • sys.argv[0]sys.argv[0] is the script name, not the first argument.
  • Dashes become underscores--max-size--max-size is read as args.max_sizeargs.max_size.
  • store_truestore_true flags default to FalseFalse — presence flips them to TrueTrue.
  • argparse exits on bad input — it prints usage and calls sys.exitsys.exit, which is usually what you want.

Practice Exercises

Exercise 1 – Read from a simulated argv

Exercise 2 – Parse a positional argument

Exercise 3 – An optional integer with a default

Summary

  • sys.argvsys.argv is the raw list of string arguments (argv[0]argv[0] is the script name).
  • argparseargparse adds types, defaults, choices, flags, validation, and auto-generated --help--help.
  • Positional args are required; --optional--optional args can have defaults; store_truestore_true makes boolean flags.
  • Pass an explicit list to parse_args([...])parse_args([...]) for testing and examples.

If this helped you, consider buying me a coffee ☕

Buy me a coffee

Was this page helpful?

Let us know how we did