Steven Bethard wrote:
> On Tue, Sep 29, 2009 at 1:31 PM, Paul Moore <p.f.moore at gmail.com> wrote:
>> 2009/9/28 Yuvgoog Greenle <ubershmekel at gmail.com>:
>>> 1. There is no chance of the script killing itself. In argparse and optparse
>>> exit() is called on every parsing error (btw because of this it sucks to
>>> debug parse_args in an interpreter).
> [...]
>> This is behavior that argparse inherits from optparse, but I believe
> it's still what 99.9% of users want. If you're writing a command line
> interface, you don't want a stack trace when there's an error message
> (which is what you'd get if argparse just raised exceptions) you want
> an exit with an error code. That's what command line applications are
> supposed to do.
>> If you're not using argparse to write command line applications, then
> I don't feel bad if you have to do a tiny bit of extra work to take
> care of that use case. In this particular situation, all you have to
> do is subclass ArgumentParser and override exit() to do whatever you
> think it should do.
>>>> 2. There is no chance the parser will print things I don't want it to print.
> [...]
>> There is only a single method in argparse that prints things,
> _print_message(). So if you want it to do something else, you can
> simply override it in a subclass. I can make that method public if
> this is a common use case.
Instead of forcing the user to override the ArgumentParser class to
change how errors are handled, I suggest adding a separate method
ArgumentParser.parse_args_with_exceptions() that raises exceptions
instead of writing to stdout/stderr and never calls sys.exit(). Then
implement ArgumentParser.parse_args() as a wrapper around
parse_args_with_exceptions():
class ArgparseError(Exception):
"""argparse-specific exception type."""
pass
class ArgumentError(ArgparseError):
# ...
class ArgumentParser(...):
# ...
def parse_args_with_exceptions(...):
# like the old parse_args(), except raises exceptions instead of
# writing to stdout/stderr or calling sys.exit()...
def parse_args(self, *args, **kwargs):
try:
self.parse_args_with_exceptions(*args, **kwargs)
except ArgparseError as e:
self.print_usage(_sys.stderr)
self.exit(status=2,
message=(_('%s: error: %s\n') % (self.prog, e,)))
# perhaps catch other exceptions that need special handling...
def error(self, message):
raise ArgparseError(message)
The exception classes should hold enough information to be useful to
non-command-line users, and obviously contain error messages that are
output to stderr by default. This would allow non-command-line users to
call parse_args_with_exceptions() and handle the exceptions however they
like.
Michael