Pass the nargs and const arguments to add_argument:
parser.add_argument('--list',
default='all',
const='all',
nargs='?',
choices=['servers', 'storage', 'all'],
help='list servers, storage, or both (default: %(default)s)')
If you want to know if --list was passed without an argument, remove the const argument, and check if args.list is None.
Documention:
nargs with '?'
One argument will be consumed from the command line if possible, and produced as a single item. If no command-line argument is present, the value from
defaultwill be produced. Note that for optional arguments, there is an additional case - the option string is present but not followed by a command-line argument. In this case the value fromconstwill be produced.
const
Answer from Francisco on Stack OverflowWhen
add_argument()is called with option strings (like-for--foo) andnargs='?'. This creates an optional argument that can be followed by zero or one command-line arguments. When parsing the command line, if the option string is encountered with no command-line argument following it, the value ofconstwill be assumed instead. See the nargs description for examples.
Pass the nargs and const arguments to add_argument:
parser.add_argument('--list',
default='all',
const='all',
nargs='?',
choices=['servers', 'storage', 'all'],
help='list servers, storage, or both (default: %(default)s)')
If you want to know if --list was passed without an argument, remove the const argument, and check if args.list is None.
Documention:
nargs with '?'
One argument will be consumed from the command line if possible, and produced as a single item. If no command-line argument is present, the value from
defaultwill be produced. Note that for optional arguments, there is an additional case - the option string is present but not followed by a command-line argument. In this case the value fromconstwill be produced.
const
When
add_argument()is called with option strings (like-for--foo) andnargs='?'. This creates an optional argument that can be followed by zero or one command-line arguments. When parsing the command line, if the option string is encountered with no command-line argument following it, the value ofconstwill be assumed instead. See the nargs description for examples.
Thanks @ShadowRanger. Subcommands is exactly what I need, combined with nargs and const. The following works:
parser = argparse.ArgumentParser()
subparser = parser.add_subparsers()
parser_list = subparser.add_parser('list')
parser_list.add_argument('list_type', default='all', const='all', nargs='?', choices=['all', 'servers', 'storage'])
parser_create = subparser.add_parser('create')
parser_create.add_argument('create_type', default='server', const='server', nargs='?', choices=['server', 'storage'])
args = parser.parse_args()
pprint(vars(args))
$ python3 ./myapp.py -h
usage: dotool.py [-h] {list,create} ...
Digital Ocean tool
positional arguments:
{list,create}
optional arguments:
-h, --help show this help message and exit
list option alone:
$ python3 ./myapp.py list
{'list_type': 'all'}
List option with a parameter:
$ python3 ./myapp.py list servers
{'list_type': 'servers'}
argparse choices allow multiple values
command line arguments - Python argparse with choices - Stack Overflow
Add "maybe you meant" in argparse `choices` argument - Ideas - Discussions on Python.org
equivalent of python argparse choices?
Videos
Hello
I would like to use the choices options to limit the valid values that are passed as argument to a script
parser = argparse.ArgumentParser()
parser.add_argument('-d', type=int, default=14, help = "enter (%(type)s) number of days to query the cms (default: %(default)s) ")
parser.add_argument('-o', default="Linux", choices=['Linux', 'Windows'], help="pass OS list separated by comma (default: %(default)s)")
parser.add_argument('-s', default="02", choices=['01','02', '03', '04'], help="pass super_status (default: %(default)s)")
args = parser.parse_args()this works fine but I am only allowed to pass one value
eg
script.py -o Windows, Linux -s 01,02
this will fail because it only accept one of the allowed values and not several.
is there a way to use the choices but allow several values i would prefer to do this instead of having to make if/then/else in the script to discard possible invalid arguments.
I found a way to get the behavior you want, but with a different syntax than what you present. You have to specify each choice with a unique parameter name/value pair. If that's ok, then the following works:
parser = argparse.ArgumentParser(prog='game.py')
parser.add_argument('--p1', choices=['a', 'b', 'c'], action='append')
args = parser.parse_args(['--p1', 'a', '--p1', 'b'])
print(args)
Result:
Namespace(p1=['a', 'b'])
but this fails appropriately:
parser = argparse.ArgumentParser(prog='game.py')
parser.add_argument('--p1', choices=['a', 'b', 'c'], action='append')
args = parser.parse_args(['--p1', 'a', '--p1', 'b', '--p1', 'x'])
print(args)
Result:
usage: game.py [-h] [--p1 {a,b,c}]
game.py: error: argument --p1: invalid choice: 'x' (choose from 'a', 'b', 'c')
I can find nothing in the docs that suggests that ArgumentParser will take a list of valid values as a parameter value, which is what your version would require.
Using nargs with choices:
In [1]: import argparse
In [2]: p = argparse.ArgumentParser()
In [3]: p.add_argument('-a',nargs='+', choices=['x','y','z'])
Out[3]: _StoreAction(option_strings=['-a'], dest='a', nargs='+', const=None, default=None, type=None, choices=['x', 'y', 'z'], help=None, metavar=None)
In [4]: p.parse_args('-a x y z x x'.split())
Out[4]: Namespace(a=['x', 'y', 'z', 'x', 'x'])
In [5]: p.parse_args('-a x y z w x'.split())
usage: ipython3 [-h] [-a {x,y,z} [{x,y,z} ...]]
ipython3: error: argument -a: invalid choice: 'w' (choose from 'x', 'y', 'z')