PythonMastery
reference 5 min read · lesson 13 of 16 in Reference

Python argparse Cheat Sheet

1 · The lesson

read

Quick reference for building command-line interfaces with argparse. For the full tutorial see CLI tools.

1. Minimal Skeleton

python
import argparse

def main():
    parser = argparse.ArgumentParser(description="Resize images.")
    parser.add_argument("path")                          # positional
    parser.add_argument("--size", type=int, default=800)  # optional
    args = parser.parse_args()
    print(args.path, args.size)

if __name__ == "__main__":
    main()

2. add_argument Parameters

ParameterPurposeExample
namePositional (e.g. "path") or flag ("-v")add_argument("file")
typeConvert string -> valuetype=int, type=Path
defaultUsed if not givendefault=80
choicesRestrict to a setchoices=["json", "csv"]
nargsHow many valuesnargs="+", nargs="?", nargs=3
requiredMake an optional arg mandatoryrequired=True
actionWhat to do (see table 4)action="store_true"
helpHelp texthelp="output dir"
destOverride attribute namedest="output_dir"
metavarDisplay name in helpmetavar="FILE"

3. Type Conversion

python
from pathlib import Path

parser.add_argument("n", type=int)
parser.add_argument("ratio", type=float)
parser.add_argument("path", type=Path)            # any callable works

def positive(s):
    v = int(s)
    if v <= 0:
        raise argparse.ArgumentTypeError(f"{v} is not positive")
    return v

parser.add_argument("--workers", type=positive, default=4)
+ setup added so this can run · defines parser, argparse
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

parser = _AutoMock('parser')
argparse = _AutoMock('argparse')

4. Actions

ActionEffectExample
storeSave value (default)--name Margaret -> args.name == "Margaret"
store_trueBoolean flag, default False--verbose
store_falseBoolean flag, default True--no-cache
store_constSave a fixed valueaction="store_const", const=42
countCount occurrences (-vvv)--verbose x 3
appendCollect into a list-x 1 -x 2 -> [1, 2]
extendLike append but flattens--tag a --tag b -> ["a", "b"]
versionPrint version and exitaction="version", version="1.0"
helpPrint help (auto on -h)-

5. Positional vs Optional

python
parser.add_argument("file")              # positional, required by default
parser.add_argument("--out", "-o")       # optional, prefix with --/-
parser.add_argument("--force", action="store_true")
+ setup added so this can run · defines parser
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

parser = _AutoMock('parser')

6. Boolean Flags

python
parser.add_argument("--verbose", "-v", action="store_true")
parser.add_argument("--no-cache", dest="cache", action="store_false")
# args.cache defaults to True; --no-cache flips it
+ setup added so this can run · defines parser
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

parser = _AutoMock('parser')

For Python 3.9+ you can also use argparse.BooleanOptionalAction:

python
parser.add_argument("--cache", action=argparse.BooleanOptionalAction, default=True)
# now --cache and --no-cache both work
+ setup added so this can run · defines parser, argparse
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

parser = _AutoMock('parser')
argparse = _AutoMock('argparse')

7. nargs Values

ValueMeaningResult
NoneDefault — exactly onestr
NExactly N (integer)list of N
"?"Zero or one (uses default / const)one value or default
"*"Zero or morelist (possibly empty)
"+"One or morenon-empty list
argparse.REMAINDEREverything that followslist
python
parser.add_argument("files", nargs="+")             # at least one
parser.add_argument("--tags", nargs="*", default=[])
parser.add_argument("--colour", nargs="?", const="red", default="black")
+ setup added so this can run · defines parser
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

parser = _AutoMock('parser')

8. Subparsers (git-style)

python
parser = argparse.ArgumentParser(prog="dev")
sub = parser.add_subparsers(dest="cmd", required=True)

p_add = sub.add_parser("add", help="add an item")
p_add.add_argument("item")

p_rm = sub.add_parser("rm", help="remove an item")
p_rm.add_argument("item")
p_rm.add_argument("--force", action="store_true")

args = parser.parse_args()
if args.cmd == "add":
    ...
elif args.cmd == "rm":
    ...
+ setup added so this can run · defines argparse
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

argparse = _AutoMock('argparse')

9. stdin and Files

python
# Use - to mean "stdin/stdout"
parser.add_argument("infile",  type=argparse.FileType("r"))
parser.add_argument("outfile", type=argparse.FileType("w"))
# python script.py - -    # reads stdin, writes stdout
+ setup added so this can run · defines parser, argparse
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

parser = _AutoMock('parser')
argparse = _AutoMock('argparse')

10. Help Text & Epilog

python
parser = argparse.ArgumentParser(
    prog="resize",
    description="Resize images by longest side.",
    epilog="Example: resize photo.jpg --size 1024",
    formatter_class=argparse.RawDescriptionHelpFormatter,
)
+ setup added so this can run · defines argparse
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

argparse = _AutoMock('argparse')

Common Patterns

python
# Verbosity counter:  -v INFO  -vv DEBUG
parser.add_argument("-v", "--verbose", action="count", default=0)
level = {0: "WARNING", 1: "INFO"}.get(args.verbose, "DEBUG")

# Log level choice
parser.add_argument("--log", choices=["DEBUG", "INFO", "WARNING", "ERROR"],
                    default="INFO")

# Variable list of files
parser.add_argument("files", nargs="+", type=Path)

# Key=value pairs
def kv(s):
    k, _, v = s.partition("=")
    if not k or not v:
        raise argparse.ArgumentTypeError("expected key=value")
    return (k, v)

parser.add_argument("-D", action="append", type=kv, default=[],
                    metavar="K=V", help="extra defines")

# Mutually exclusive group
g = parser.add_mutually_exclusive_group(required=True)
g.add_argument("--json", action="store_true")
g.add_argument("--csv",  action="store_true")
+ setup added so this can run · defines parser, args, Path, argparse
# Lightweight mock for objects whose attributes/methods aren't critical
class _AutoMock:
    def __init__(self, name='mock'): self._name = name
    def __getattr__(self, k): return _AutoMock(self._name + '.' + k)
    def __call__(self, *a, **kw):
        print('-> ' + self._name + '() called')
        return _AutoMock(self._name + '()')
    def __repr__(self): return '<mock ' + self._name + '>'
    def __str__(self): return '<mock ' + self._name + '>'
    def __bool__(self): return True
    def __iter__(self): return iter([])
    def __len__(self): return 0
    def __getitem__(self, k): return _AutoMock(self._name + '[...]')
    def __setitem__(self, k, v): pass
    def __enter__(self): return self
    def __exit__(self, *a): return False
    async def __aenter__(self): return self
    async def __aexit__(self, *a): return False
    def __add__(self, o): return self
    def __radd__(self, o): return self
    def __sub__(self, o): return self
    def __mul__(self, o): return self
    def __rmul__(self, o): return self
    def __truediv__(self, o): return self
    def __eq__(self, o): return isinstance(o, _AutoMock)
    def __hash__(self): return hash(self._name)
    def __lt__(self, o): return True
    def __le__(self, o): return True
    def __gt__(self, o): return False
    def __ge__(self, o): return False
    def __mro_entries__(self, bases): return (object,)

parser = _AutoMock('parser')
args = _AutoMock('args')
Path = _AutoMock('Path')
argparse = _AutoMock('argparse')

Common Errors

Error / SymptomCauseFix
args.count + 1 -> TypeError: can only concatenate str ...Forgot type=intPass type=int
AttributeError: 'Namespace' object has no attribute 'cmd'Subparsers added without dest=Use add_subparsers(dest="cmd")
Got "a b c" as single string instead of listMissing nargs="+"Add nargs="+"
Mandatory flag isn't enforcedOptional args are optional by defaultPass required=True
Help shows ugly newlinesDefault formatter strips themUse RawDescriptionHelpFormatter or RawTextHelpFormatter
error: unrecognized argumentsTypo, missing space, or args after -- not declaredCheck spelling; use parser.parse_known_args() if you really want
Default appended to user listdefault=[] shared with action="append"Use default=[] and check; or set default=None and or []

See Also