Handle invalid arguments with argparse in Python

白昼怎懂夜的黑 提交于 2019-12-05 13:01:09

You might want to use parse_known_args and then take a look at the second item in the tuple to see what arguments were not understood.

That said, I believe this will only help with extra arguments, not expected arguments that have invalid values.

hpaulj

Some previous questions:

Python argparse and controlling/overriding the exit status code

I want Python argparse to throw an exception rather than usage

and probably more.

The argparse documentation talks about using parse_known_args. This returns a list of arguments that it does not recognize. That's a handy way of dealing with one type of error.

It also talks about writing your own error and exit methods. That error that you don't like passes through those 2 methods. The proper way to change those is to subclass ArgumentParser, though you can monkey-patch an existing parser. The default versions are at the end of the argparse.py file, so you can study what they do.

A third option is to try/except the Systemexit.

try:
    parser=argparse.ArgumentParser()
    args=parser.parse_args()
except SystemExit:
    exc = sys.exc_info()[1]
    print(exc)

This way, error/exit still produce the error message (to sys.stderr) but you can block exit and go on and do other things.

1649:~/mypy$ python stack38340252.py -x
usage: stack38340252.py [-h]
stack38340252.py: error: unrecognized arguments: -x
2

One of the earlier question complained that parser.error does not get much information about the error; it just gets a formatted message:

def myerror(message):
    print('error message')
    print(message)

parser=argparse.ArgumentParser()
parser.error = myerror
args=parser.parse_args()

displays

1705:~/mypy$ python stack38340252.py -x
error message
unrecognized arguments: -x

You could parse that message to find out the -x is the unrecognized string. In an improvement over earlier versions it can list multiple arguments

1705:~/mypy$ python stack38340252.py foo -x abc -b
error message
unrecognized arguments: foo -x abc -b

Look up self.error to see all the cases that can trigger an error message. If you need more ideas, focus on a particular type of error.

===============

The unrecognized arguments error is produced by parse_args, which calls parse_known_args, and raises this error if the extras is not empty. So its special information is the list of strings that parse_known_args could not handle.

parse_known_args for its part calls self.error if it traps an ArgumentError. Generally those are produced when a specific argument (Action) has problems. But _parse_known_args calls self.error if required Action is missing, or if there's a mutually-exclusive-group error. choices can produce a different error, as can type.

You can try subclassing argparse.ArgumentParser() and overriding the error method.

From the argparse source:

def error(self, message):
        """error(message: string)

        Prints a usage message incorporating the message to stderr and
        exits.

        If you override this in a subclass, it should not return -- it
        should either exit or raise an exception.
        """
        self.print_usage(_sys.stderr)
        self.exit(2, _('%s: error: %s\n') % (self.prog, message))

Since the error code 2 is reserved for internal docker usage, I'm using the following to parse arguments in scripts inside docker containers:

ERROR_CODE = 1
class DockerArgumentParser(argparse.ArgumentParser):
    def error(self, message):
        """error(message: string)

    Prints a usage message incorporating the message to stderr and
    exits.

    If you override this in a subclass, it should not return -- it
    should either exit or raise an exception.

    Overrides error method of the parent class to exit with error code 1 since default value is
    reserved for internal docker usage
    """
    self.print_usage(sys.stderr)
    args = {'prog': self.prog, 'message': message}
    self.exit(ERROR_CODE, '%(prog)s: error: %(message)s\n' % args)
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!