import argparse, sys
print(sys.argv)
parser = argparse.ArgumentParser()
parser.add_argument('--arg', nargs='+', choices=[1,2,3], type=int)
args = parser.parse_args()
print(args)
some runs
1455:~/mypy$ python stack49824248.py --arg 1
['stack49824248.py', '--arg', '1']
Namespace(arg=[1])
1455:~/mypy$ python stack49824248.py --arg 1 3 2 1
['stack49824248.py', '--arg', '1', '3', '2', '1']
Namespace(arg=[1, 3, 2, 1])
1456:~/mypy$ python stack49824248.py --arg 1,2
['stack49824248.py', '--arg', '1,2']
usage: stack49824248.py [-h] [--arg {1,2,3} [{1,2,3} ...]]
stack49824248.py: error: argument --arg: invalid int value: '1,2'
The shell, together with the interpreter, splits the input on spaces, and provides a list of strings in sys.argv
. That's what parser
handles.
With +
, the --arg
action accepts a list of strings (to the end or next flag). Each string is passed through the type
function, and the result compared to the choices
(if provided). In this case, type
is int
, so the choices can be integers as well. Without the type
, choices
would have to be ['1','2','3']
.
If I change the argument to:
parser.add_argument('--arg', nargs='+', choices=['1','2','3','1,2','2,3'])
it will accept some strings with commas:
1456:~/mypy$ python stack49824248.py --arg 1
['stack49824248.py', '--arg', '1']
Namespace(arg=['1'])
1505:~/mypy$ python stack49824248.py --arg 1,2
['stack49824248.py', '--arg', '1,2']
Namespace(arg=['1,2'])
1505:~/mypy$ python stack49824248.py --arg 1,2,3
['stack49824248.py', '--arg', '1,2,3']
usage: stack49824248.py [-h] [--arg {1,2,3,1,2,2,3} [{1,2,3,1,2,2,3} ...]]
stack49824248.py: error: argument --arg: invalid choice: '1,2,3' (choose from '1', '2', '3', '1,2', '2,3')
I didn't include the '1,2,3' choice, so it rejected that. Note also that I dropped the int
type
, since int('1,2')
will fail.
So if you need to accept '1,2,3', do your own split and choices test after parsing (or possibly as a custom Action
class).
In [16]: [(int(x) in [1,2,3]) for x in '1,2,3'.split(',')]
Out[16]: [True, True, True]
In [17]: [(int(x) in [1,2,3]) for x in '1,2,4'.split(',')]
Out[17]: [True, True, False]
In [18]: [(int(x) in [1,2,3]) for x in '1,a,4'.split(',')]
....
ValueError: invalid literal for int() with base 10: 'a'