Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python argparse and controlling/overriding the exit status code

Apart from tinkering with the argparse source, is there any way to control the exit status code should there be a problem when parse_args() is called, for example, a missing required switch?

like image 873
Kev Avatar asked May 09 '11 22:05

Kev


1 Answers

I'm not aware of any mechanism to specify an exit code on a per-argument basis. You can catch the SystemExit exception raised on .parse_args() but I'm not sure how you would then ascertain what specifically caused the error.

EDIT: For anyone coming to this looking for a practical solution, the following is the situation:

  • ArgumentError() is raised appropriately when arg parsing fails. It is passed the argument instance and a message
  • ArgumentError() does not store the argument as an instance attribute, despite being passed (which would be convenient)
  • It is possible to re-raise the ArgumentError exception by subclassing ArgumentParser, overriding .error() and getting hold of the exception from sys.exc_info()

All that means the following code - whilst ugly - allows us to catch the ArgumentError exception, get hold of the offending argument and error message, and do as we see fit:

import argparse import sys  class ArgumentParser(argparse.ArgumentParser):         def _get_action_from_name(self, name):         """Given a name, get the Action instance registered with this parser.         If only it were made available in the ArgumentError object. It is          passed as it's first arg...         """         container = self._actions         if name is None:             return None         for action in container:             if '/'.join(action.option_strings) == name:                 return action             elif action.metavar == name:                 return action             elif action.dest == name:                 return action      def error(self, message):         exc = sys.exc_info()[1]         if exc:             exc.argument = self._get_action_from_name(exc.argument_name)             raise exc         super(ArgumentParser, self).error(message)  ## usage: parser = ArgumentParser() parser.add_argument('--foo', type=int) try:     parser.parse_args(['--foo=d']) except argparse.ArgumentError, exc:     print exc.message, '\n', exc.argument 

Not tested in any useful way. The usual don't-blame-me-if-it-breaks indemnity applies.

like image 157
Rob Cowie Avatar answered Sep 17 '22 23:09

Rob Cowie