[issue35495] argparse does not honor default argument for nargs=argparse.REMAINDER argument

Michael Blahay report at bugs.python.org
Fri May 10 16:12:08 EDT 2019


Michael Blahay <mblahay at gmail.com> added the comment:

With the optional arguments, the determination about whether to use the default value is made based on whether the flag is present or not. When positional arguments are involved, the need for the defaults seems to in part be determined based on whether the argument exists. The fact that * and REMAINDER are zero-to-many in nature add some ambiguity into the situation. For the *, it seems that the positional argument only exists if there is at least one actual argument value that it can consume.

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('foo', nargs=1,default=['none'])
#parser.add_argument('bar', nargs=argparse.REMAINDER,default=['nothing'])
parser.add_argument('baz', nargs='*', default=['nada'])
parser.parse_args('a b'.split())

Out[25]: Namespace(baz=['b'], foo=['a'])

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('foo', nargs=1,default=['none'])
#parser.add_argument('bar', nargs=argparse.REMAINDER,default=['nothing'])
parser.add_argument('baz', nargs='*', default=['nada'])
parser.parse_args('a'.split())

Out[26]: Namespace(baz=['nada'], foo=['a'])

Mean while, the REMAINDER option makes the argument act as if it exists regardless of whether an actual argument value exists.

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('foo', nargs=1,default=['none'])
parser.add_argument('bar', nargs=argparse.REMAINDER,default=['nothing'])
#parser.add_argument('baz', nargs='*', default=['nada'])
parser.parse_args('a b'.split())

Out[27]: Namespace(bar=['b'], foo=['a'])

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('foo', nargs=1,default=['none'])
parser.add_argument('bar', nargs=argparse.REMAINDER,default=['nothing'])
#parser.add_argument('baz', nargs='*', default=['nada'])
parser.parse_args('a'.split())

Out[28]: Namespace(bar=[], foo=['a'])

To conclude, * and REMAINDER perform similar, but different, roles when used with positional arguments. With edge cases like the ones laid out above, it can be hard to conceptualize what the exact behavior should be. I will recommend that the documentation be updated to convey the following message: "When used with positional arguments, REMAINDER will never use the designated default value list. It will instead return an empty list if there are no values for the argument to consume. If the use of default values is desired, then * must be used."

----------

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue35495>
_______________________________________


More information about the Python-bugs-list mailing list