0

I'm using argparse package to parse command line arguments. Now I want to accept exactly 0, 1 or 2 strings and put them into a list.

My current approach looks like:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('strs', nargs='*')

print(parser.parse_args([]).strs)
print(parser.parse_args(['AAA']).strs)
print(parser.parse_args(['AAA', 'BBB']).strs)
print(parser.parse_args(['AAA', 'BBB', 'CCC']).strs)

For the 1st, 2nd and 3rd parse_args() the results are expected. For the last one my current approach is if len(parse_args.strs) > 2: raise. Is there any better approach that could let argparse check for me?

timrau
  • 22,578
  • 4
  • 51
  • 64
  • That duplicate's answer gives a custom Action class such as I suggested. But I'm not sure it's an improvement over post-parsing testing. – hpaulj Aug 23 '16 at 22:29

1 Answers1

1

There isn't a means in argparse to accept a range of nargs, just values like 1,2,'+','*'.

You could write a custom Action class that would check the number of values that the nargs='*' passes it. But I think it would be just as easy to perform that test after parsing.

I could find a bug/issue that explores adding a range nargs option if you really want to get into that.

If you didn't have other positionals you could define 3 positionals, 2 of them with ?. You might even be able to combine them into one list with a common name and 'append' action. I'll explore that.

In [573]: p=argparse.ArgumentParser()
In [574]: p.add_argument('str',action='append')
In [575]: p.add_argument('str',nargs='?',action='append')
In [576]: p.add_argument('str',nargs='?',action='append')

In [577]: p.print_help()
usage: ipython3 [-h] str [str] [str]

positional arguments:
  str
  str
  str

optional arguments:
  -h, --help  show this help message and exit

In [578]: p.parse_args('1 2 3'.split())
Out[578]: Namespace(str=['1', '2', '3'])
In [579]: p.parse_args('1 3'.split())
Out[579]: Namespace(str=['1', '3', None])
In [580]: p.parse_args('1'.split())
Out[580]: Namespace(str=['1', None, None])

Got the default Nones. I can correct that with

p.add_argument('str', nargs='?', action='append', default=argparse.SUPPRESS)

In [586]: p.parse_args('1 2'.split())
Out[586]: Namespace(str=['1', '2'])
In [588]: p.parse_args('1 2 3 4'.split())
usage: ipython3 [-h] str [str] [str]
ipython3: error: unrecognized arguments: 4

(oops, this is coded for 1-3 argument, but you get the idea).

hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • I believe you're referencing this open issue: http://bugs.python.org/issue11354. It appears to have had no activity since 2013. – Akshat Mahajan Aug 23 '16 at 16:58
  • Yes, there's a big backlog of partially addressed issues. This a low priority enhancement. It requires bigger changes in the help and usage formatting than in the parsing code itself. – hpaulj Aug 23 '16 at 17:02