Batu Lab NotesPractical developer guides

Return a controlled parser error for an invalid mode

By Batu ยท English technical notes

Also published in our Blogger archive.

A command-line parser normally writes an error and exits when it rejects input. For a program that needs to decide its own response, create ArgumentParser with exit_on_error=False. In this example, the positional mode accepts only fast or safe. Parsing the synthetic input turbo raises argparse.ArgumentError, which the program converts into the stable message invalid mode: turbo.

The assertion deliberately checks that the parser reported an invalid choice, while the printed result comes from application code rather than from argparse's formatted diagnostic. That distinction keeps stdout deterministic and avoids coupling a user-facing protocol to parser wording, usage formatting, or future documentation changes. The else branch ensures the example fails if the invalid input is accidentally accepted.

This approach handles parser errors that are raised as ArgumentError; it is not a universal replacement for validating every command-line failure. For example, application-specific constraints that depend on files, permissions, or multiple parsed values still need explicit validation after parsing. If a command should preserve the conventional command-line behavior, leaving exit_on_error at its default is often more appropriate.

exit_on_error=False was added in Python 3.9. The official ArgumentParser documentation describes the default exit behavior and the catchable-error option; argument choices are documented in add_argument().

AI assistance disclosure: This article was drafted with AI assistance and should be adapted to the application's error protocol.

import argparse


parser = argparse.ArgumentParser(prog="runner", exit_on_error=False)
parser.add_argument("mode", choices=("fast", "safe"))

try:
    parser.parse_args(["turbo"])
except argparse.ArgumentError as error:
    assert "invalid choice" in str(error)
    message = "invalid mode: turbo"
else:
    raise AssertionError("invalid mode was accepted")

print(message)
invalid mode: turbo