Batu Lab NotesPractical developer guides

Make argparse exit behavior testable

By Batu ยท English technical notes

Also published in our Blogger archive.

Quick answer

argparse reports invalid command-line choices by writing a diagnostic and raising SystemExit with its error status.

Example

The test redirects stderr, parses an invalid --format csv, and asserts code 2 plus the invalid choice text. Capturing both pieces makes the CLI contract testable without allowing the test runner to exit.

import argparse, contextlib, io
p = argparse.ArgumentParser(prog='report')
p.add_argument('--format', choices=['json'])
stderr = io.StringIO()
with contextlib.redirect_stderr(stderr):
    try:
        p.parse_args(['--format', 'csv'])
    except SystemExit as e:
        code = e.code
assert code == 2 and 'invalid choice' in stderr.getvalue()
print('invalid-argument=2')

Expected stdout:

invalid-argument=2

Reading the result

For an installed command, add a subprocess test too. That catches packaging and stream-wiring errors that an in-process parser test cannot observe.

Test the help path separately from the invalid-argument path. Help commonly exits successfully, whereas a rejected value uses the parser error status; callers may rely on that difference.

Redirecting stderr is necessary because argparse owns its diagnostic stream. The test therefore verifies both an observable message category and the process-style exit code.

Sources

- Python argparse documentation

Prepared with AI assistance. The example uses synthetic data; its stated limits apply.