I want to generate custom error messages for particular usage errors in my command-line program that uses the argparse
library. I know I can override the general presentation of the error by subclassing argparse.ArgumentParser
:
class HelpParser(argparse.ArgumentParser):
def error(self, message):
sys.stderr.write('error: %s\n' % message)
sys.exit(2)
parser = HelpParser(... ...)
args = parser.parse_args()
But when my error
method is called, message
has already been formatted by the library. For example,
> python prog.py old stuff
usage: prog [-h] {hot,cold,rain,snow} ...
prog: error: argument subparser: invalid choice: 'old' (choose from u'hot', u'cold', u'rain', u'snow')
How can I change how the stuff after error:
is presented, for instance to
usage: prog [-h] {hot,cold,rain,snow} ...
error: 'old' is not a valid option. select from 'hot', 'cold', 'rain', 'snow'
?
Optional Arguments To add an optional argument, simply omit the required parameter in add_argument() . args = parser. parse_args()if args.
The store_true option automatically creates a default value of False. Likewise, store_false will default to True when the command-line argument is not present. The source for this behavior is succinct and clear: http://hg.python.org/cpython/file/2.7/Lib/argparse.py#l861.
Python argparse optional argument The example adds one argument having two options: a short -o and a long --ouput . These are optional arguments. The module is imported. An argument is added with add_argument .
>>> parser = argparse.ArgumentParser(description='Process some integers.') The ArgumentParser object will hold all the information necessary to parse the command line into Python data types.
Looking at the source code, you could over-ride this particular
error message by overriding this method:
def _check_value(self, action, value):
# converted value must be one of the choices (if specified)
if action.choices is not None and value not in action.choices:
args = {'value': value,
'choices': ', '.join(map(repr, action.choices))}
msg = _('invalid choice: %(value)r (choose from %(choices)s)')
raise ArgumentError(action, msg % args)
The issue is that if you wanted to override all possible error messages, you'd have to basically re-write this module. All the various error messages are pre-formatted throughout -in the various methods that detect each type of error.
Adding to @Gerrat's answer, the _
function is imported as
from gettext import gettext as _, ngettext
It is using the gettext
module, https://docs.python.org/2/library/gettext.html, to enable internationalization. I'm not familiar with that module, but presumably you could use it to perform a certain amount English paraphrasing. But maybe not as much as you'd like.
Error messages pass through several levels. Functions like _check_values
write the basic message. ArgumentError
adds the argument name (argument subparser:
in your example). parser.error
adds the usage
and prog
. parser.exit
takes care of the sys.exit
step.
def error(self, message):
...
self.print_usage(_sys.stderr)
args = {'prog': self.prog, 'message': message}
self.exit(2, _('%(prog)s: error: %(message)s\n') % args)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With