1

I'm considering adding argparse to existing batch jobs which run python. These jobs take command line arguments which can vary depending on how the jobs are to run. I'd like to use the named argument feature in argparse but instead of exiting the job if an argument is eg. missing or misnamed, I'd like to trap that error and hand the subsequent processing off to existing python routines which handle the job exit. These routines create logs, backout db transactions, flush files to disk and email whoever is responsible for the job of the problem encountered.

I've tried using python try except block (below) to trap the error but it fails. I've also seen solutions which involve subclassing argparse but this results in a much more complicated code base than prior to introducing argparse and is therefore counter-productive.

Is there a simple solution to this problem I'm missing? Many thanks.

try:
    args = my_parser.parse_args()
except Exception as parseError:
    do my stuff
0

2 Answers 2

1

You need to set the exit_on_error option to False when creating the ArgumentParser object. Then it will raise an exception instead of exiting the script.

my_parser = argparse.ArgumentParser(exit_on_error=False)
# Add options to my_parser
try:
    args = my_parser.parse_args()
except argparse.ArgumentError as parseError:
    # do my stuff

If you're using an older version of argparse that doesn't have this option, you can make a subclass of ArgumentParser that overrides the ArgumentParser.exit() method to raise ane exception instead of exiting.

class ErrorCatchingArgumentParser(argparse.ArgumentParser):
    def exit(self, status=0, message=None):
        if status:
            raise Exception(f'Exiting because of an error: {message}')
        exit(status)

my_parser = ErrorCatchingArgumentParser()
# Add options to my_parser
try:
    args = my_parser.parse_args()
except Exception as parseError:
    # do my stuff
Sign up to request clarification or add additional context in comments.

4 Comments

exit_on_error is a relatively new addition. For older versions is possible to wrap the parse_args in an if/execpt and capture the sys.exit(). ipython interactive sessions do this. Or you can customize the parser.exit method. docs.python.org/3/library/argparse.html#exiting-methods
@hpaulj I assume you mean try/except, which is what the OP tried to do but it didn't work. Which suggests he's using the newer version.
except SystemExit works. SystemExit is not a subclass of Exception.
exit_on_error was not added until 3.9. (docs.python.org/3/library/argparse.html) but I'm confined to 3.6. so exit_on_error generates TypeError: __init__() got an unexpected keyword argument 'exit_on_error'
0

In an ipython session:

In [3]: parser = argparse.ArgumentParser()
In [4]: parser.parse_args(['foo'])
usage: ipython3 [-h]
ipython3: error: unrecognized arguments: foo
An exception has occurred, use %tb to see the full traceback.
SystemExit: 2

/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py:3426: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.
  warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
In [5]: try:
   ...:     parser.parse_args(['foo'])
   ...: except SystemExit:
   ...:     pass
   ...: 
usage: ipython3 [-h]
ipython3: error: unrecognized arguments: foo

And capturing the traceback:

In [12]: import sys
In [13]: try:
    ...:     parser.parse_args(['foo'])
    ...: except SystemExit:
    ...:     tb = sys.exc_info()
    ...: 
    ...: 
usage: ipython3 [-h]
ipython3: error: unrecognized arguments: foo
In [14]: print(tb)
(<class 'SystemExit'>, SystemExit(2), <traceback object at 0x7f9ffe415cc0>)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.