argparse subcommand error message

If I tweak your script

p = ArgumentParser(prog="test")
p.add_argument('--bar')
sp = p.add_subparsers(dest='cmd')
sp1 = sp.add_parser('foo')
sp1.add_argument('--baz')
print p.parse_known_args()

the output is

1517:~/mypy$ python2.7 stack25333847.py foo --bar
(Namespace(bar=None, baz=None, cmd='foo'), ['--bar'])

Parser p encounters the foo, one of the allowed sp choices. So it now delegates parsing to the subparser, sp1. sp1 does not recognize --bar, so it returns that to the main parser in its list of unrecognized arguments. The default action is for the main parser to pass it on out, as though it(self) did not recognized the string.

Due its position after foo, --bar is not recognized by either parser. Same would go for ['foo', '--boo'].

Delegation to the subparser is done in the __call__ method of sp (the subparsers action). In part it reads:

def __call__(self, parser, namespace, values, option_string=None):
    ...
    # parse all the remaining options into the namespace
    # store any unrecognized options on the object, so that the top
    # level parser can decide what to do with them
    namespace, arg_strings = parser.parse_known_args(arg_strings, namespace)
    if arg_strings:
        vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, [])
        getattr(namespace, _UNRECOGNIZED_ARGS_ATTR).extend(arg_strings)

So the handling of unrecognized_args is left, by design, to the main parser (the one who calls parse_args rather than parse_known_args).


A different error, such as omitting a value for --baz does generate the error message in the subparser:

1523:~/mypy$ python2.7 stack25333847.py foo --baz
usage: test foo [-h] [--baz BAZ]
test foo: error: argument --baz: expected one argument

I have figured out a way of generating:

usage: test foo [-h] [--baz BAZ]
test foo: error: unrecognized arguments: --bar

though it's not short and sweet. I subclass argparse._SubParsersAction; give it a new __call__ that uses parse_args instead of parse_known_args. I also have to change the main parser registry. (I can add the code if wanted).