Raise exception if ArgumentParser encounters unknown argument

Question:

I’m using the Python (version 3.9.4) library argparse to parse a small number of option flags. For a number of reasons, I’d like to handle errors in my code rather than argparse.ArgumentParser. Namely, how an unrecognized argument is handled. For example, if I ran my-python-program --foobar, I’d like to be able to catch an exception and perform work there. This testcase disables almost all of the errors I’ve tried, except for an invalid argument:

import argparse
import sys

try:
  parser = argparse.ArgumentParser(add_help=False, exit_on_error=False, usage=None)
  parser.add_argument("--help", action="store_true", default=False)
  parser.add_argument("--hello", default="Hello, world!")
  args = parser.parse_args()
  print(args.help, args.hello)

except Exception as err:
  print("a problem occurred!", file=sys.stderr)
  print(f"error: {err}", file=sys.stderr)

Instead, running my-python-program --foobar gives me:

usage: my-python-program [--help] [--hello HELLO]
my-python-program: error: unrecognized arguments: --foobar
Asked By: uplime

||

Answers:

If you look at the Python argparse source code, you can see that it calls self.error on an error. This function (at the bottom of the file), by default, prints the error message and quits. You can override this method in a subclass to raise an error instead.

import argparse
import sys

class MyArgumentParser(argparse.ArgumentParser):
  """An argument parser that raises an error, instead of quits"""
  def error(self, message):
    raise ValueError(message)

try:
  parser = MyArgumentParser(add_help=False, exit_on_error=False, usage=None)
  parser.add_argument("--help", action="store_true", default=False)
  parser.add_argument("--hello", default="Hello, world!")
  args = parser.parse_args()
  print(args.help, args.hello)

except Exception as err:
  print("a problem occurred!", file=sys.stderr)
  print(f"error: {err}", file=sys.stderr)

Output:

$ python3 test.py --foobar
a problem occurred!
error: unrecognized arguments: --foobar
Answered By: David