Argument groups and mutual exclusion

argparse · Advanced · 9 min

Large CLIs need readable help sections and must reject combinations like --quiet --verbose.

Argument groups only affect help output. g = parser.add_argument_group("output", "description") creates a titled section; arguments added with g.add_argument(...) are listed under it instead of the default "options" heading. Parsing is unchanged.

Mutually exclusive groups affect parsing: at most one of their arguments may be given.

mx = parser.add_mutually_exclusive_group()
mx.add_argument("--quiet", action="store_true")
mx.add_argument("--verbose", action="store_true")

Supplying both gives argument --verbose: not allowed with argument --quiet. Pass required=True to demand exactly one. Usage shows the group as [--quiet | --verbose].

You can nest a mutually exclusive group inside an argument group to get both a heading and exclusivity: group.add_mutually_exclusive_group(). Other nesting (groups inside mutually exclusive groups) is deprecated.

Mutually exclusive groups only handle "pick one". For richer rules ("--key requires --cert", "at least one of A or B") check after parsing and call parser.error("..."), which prints usage and exits with status 2 exactly like built-in errors, so your custom checks feel native.

Example

import argparse

p = argparse.ArgumentParser(prog="sync")
mx = p.add_mutually_exclusive_group()
mx.add_argument("-q", "--quiet", action="store_true")
mx.add_argument("-v", "--verbose", action="store_true")

net = p.add_argument_group("network", "connection settings")
net.add_argument("--cert")
net.add_argument("--key")

for argv in (["-v"], ["-q", "-v"], ["--key", "k.pem"]):
    try:
        a = p.parse_args(argv)
        if a.key and not a.cert:
            p.error("--key requires --cert")
        print("ok", argv)
    except SystemExit as e:
        print("exit", e.code, argv)
# ok ['-v']
# sync: error: argument -v/--verbose: not allowed with argument -q/--quiet
# exit 2 ['-q', '-v']
# sync: error: --key requires --cert
# exit 2 ['--key', 'k.pem']

Remember

  • Argument groups only change help layout
  • Mutually exclusive groups reject combinations; required=True demands one
  • Use parser.error() for custom cross-argument rules

Watch out for

  • Expecting add_argument_group to enforce anything; it is purely cosmetic.

Check yourself

  1. How do you report a custom validation failure so it looks like argparse's own errors?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.python.org/3/library/argparse.html#mutual-exclusion