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 default will 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 from const will be produced.

const

When add_argument() is called with option strings (like -f or --foo) and nargs='?'. 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 of const will be assumed instead. See the nargs description for examples.

Answer from Francisco on Stack Overflow
🌐
Python
docs.python.org › 3 › library › argparse.html
argparse — Parser for command-line options, arguments and subcommands
These can be handled by passing a sequence object as the choices keyword argument to add_argument(). When the command line is parsed, argument values will be checked, and an error message will be displayed if the argument was not one of the ...
Top answer
1 of 2
133

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 default will 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 from const will be produced.

const

When add_argument() is called with option strings (like -f or --foo) and nargs='?'. 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 of const will be assumed instead. See the nargs description for examples.

2 of 2
16

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'}
Discussions

argparse choices allow multiple values
specify nargs. '+' will collect 1+ arguments. https://repl.it/repls/AjarTepidMemwatch More on reddit.com
🌐 r/learnpython
1
1
February 25, 2020
command line arguments - Python argparse with choices - Stack Overflow
I want to run my python program from the command line with some options. E.g. say my program has 4 modes, and I want it to use mode 2 by giving it the following arguments: $ python main.py --mode 2... More on stackoverflow.com
🌐 stackoverflow.com
Add "maybe you meant" in argparse `choices` argument - Ideas - Discussions on Python.org
Argpars is definitely aimed at the end user, and it would be nicer if it assumes what you mean. import argparse parser = argparse.ArgumentParser() parser.add_argument("--style", "-s", choices=["Bold", "Italic", "Normal", "Nope"]) args = parser.parse_args(["-s", "None"]) usage: temp_iiec_codefile.py ... More on discuss.python.org
🌐 discuss.python.org
1
November 23, 2022
equivalent of python argparse choices?
Is there an equivalent to python argparse choice, e.g.: parser.add_argument ('--rate', choices=('1/3', '1/2', '2/3', '3/4', '3/5', '4/5', ... More on github.com
🌐 github.com
5
February 2, 2017
🌐
Python.org
discuss.python.org › python help
Complement of choices in argparse - Python Help - Discussions on Python.org
August 8, 2024 - Introduce a complement to choices in argument parser’s add_argument Proposal: The choices kwarg handling in argparse._ActionsContainer.add_argument enables user to restrict the argument’s value to a specified list of approved values. The feature being proposed will allow users to only accept ...
🌐
Reddit
reddit.com › r/learnpython › argparse choices allow multiple values
r/learnpython on Reddit: argparse choices allow multiple values
February 25, 2020 -

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.

🌐
Plain English
python.plainenglish.io › python-case-in-sensitive-argparse-choices-a380e9169fff
Python: Case In-sensitive argparse “choices” | by Konstantinos Patronas | Python in Plain English
August 23, 2020 - parser = argparse.ArgumentParser()parser.add_argument('--ssh-gw', action = 'store', type = str, help = "SSH Gateway.", required = False, choices = ["grvgw1","grvgw2","grvgw3","grvgw4"], default = False)
🌐
Python.org
discuss.python.org › ideas
Add "maybe you meant" in argparse `choices` argument - Ideas - Discussions on Python.org
November 23, 2022 - Argpars is definitely aimed at the end user, and it would be nicer if it assumes what you mean. import argparse parser = argparse.ArgumentParser() parser.add_argument("--style", "-s", choices=["Bold", "Italic", "Normal", "Nope"]) args = parser.parse_args(["-s", "None"]) usage: temp_iiec_codefile.py [-h] [--style {Bold,Italic,Normal,Nope}] temp_iiec_codefile.py: error: argument --style/-s: invalid choice: 'None', maybe you meant 'Nope'?
Find elsewhere
🌐
Python Module of the Week
pymotw.com › 2 › argparse
argparse – Command line option and argument parsing. - Python Module of the Week
import argparse parser = argparse.ArgumentParser() parser.add_argument('--mode', choices=('read-only', 'read-write')) print parser.parse_args() If the argument to --mode is not one of the allowed values, an error is generated and processing stops. $ python argparse_choices.py -h usage: argparse_choices.py [-h] [--mode {read-only,read-write}] optional arguments: -h, --help show this help message and exit --mode {read-only,read-write} $ python argparse_choices.py --mode read-only Namespace(mode='read-only') $ python argparse_choices.py --mode invalid usage: argparse_choices.py [-h] [--mode {read-only,read-write}] argparse_choices.py: error: argument --mode: invalid choice: 'invalid' (choose from 'read-only', 'read-write') Although file objects can instantiated with a single string argument, that does not allow you to specify the access mode.
🌐
Python documentation
docs.python.org › 3 › howto › argparse.html
Argparse Tutorial — Python 3.14.3 documentation
The standard library includes two other libraries directly related to command-line parameter processing: the lower level optparse module (which may require more code to configure for a given application, but also allows an application to request behaviors that argparse doesn’t support), and the very low level getopt (which specifically serves as an equivalent to the getopt() family of functions available to C programmers).
🌐
mkaz.blog
mkaz.blog › working-with-python › argparse
Parse Command-Line Arguments with Argparse
September 19, 2025 - parser = argparse.ArgumentParser() ... -c hi -c hello -c hey ~ C: ['hi', 'hello', 'hey'] If you only want a set of allowed values to be used, you can set the choices list, which will display an error if invalid entry....
🌐
Flexiple
flexiple.com › python › python-argparse-list
Python argparse - Flexiple
March 27, 2024 - If users provide invalid data, argparse will raise an error and display the appropriate help message. # Add an argument with a restricted choices parser.add_argument('--mode', choices=['low', 'medium', 'high'], help='Choose processing mode')
🌐
DEV Community
dev.to › usooldatascience › mastering-pythons-argparse-a-comprehensive-guide-for-beginners-48fn
Mastering Python’s argparse: A Comprehensive Guide for Beginners - DEV Community
September 15, 2024 - Validate inputs: Use choices and type to ensure that users provide valid inputs. Keep it simple: Try not to overload your script with too many arguments unless absolutely necessary. Structure your commands: For complex tools, use subparsers to separate different commands logically. The argparse module is essential for writing professional, user-friendly Python ...
🌐
GitHub
github.com › carlobaldassi › ArgParse.jl › issues › 39
equivalent of python argparse choices? · Issue #39 · carlobaldassi/ArgParse.jl
February 2, 2017 - Is there an equivalent to python argparse choice, e.g.: parser.add_argument ('--rate', choices=('1/3', '1/2', '2/3', '3/4', '3/5', '4/5', '5/6', '7/9', '8/9', '9/10', '25/36', '26/45'), default='2/3')
Author   nbecker
🌐
Python.org
discuss.python.org › ideas
Argparse: Allow combining `type` and `choices` - Ideas - Discussions on Python.org
April 17, 2025 - Currently, combining type and choices in an argparse Action gives weird usage strings. As a toy example: import argparse parser = argparse.ArgumentParser() names = ["mo", "tu", "we", "th", "fr", "sa", "su"] days = [1,2,3,4,5,6,7] def name_day(value): return names.index(value) + 1 parser.add_argument( '--days', type=name_day, choices=days, default=["mo"], ) parser.parse_args() This will result in the following usage message: usage: example.py [-h] [--days {1,2,3,4,5,6,7...
🌐
Real Python
realpython.com › command-line-interfaces-python-argparse
Build Command-Line Interfaces With Python's argparse – Real Python
December 14, 2024 - Another interesting possibility in argparse CLIs is that you can create a domain of allowed values for a specific argument or option. You can do this by providing a list of accepted values using the choices argument of .add_argument().
🌐
GeeksforGeeks
geeksforgeeks.org › python › command-line-option-and-argument-parsing-using-argparse-in-python
Command-Line Option and Argument Parsing using argparse in Python - GeeksforGeeks
July 12, 2025 - Command line arguments are those values that are passed during the calling of the program along with the calling statement. Usually, python uses sys.argv array to deal with such arguments but here we describe how it can be made more resourceful and user-friendly by employing argparse module.
🌐
OMZ Software
omz-software.com › editorial › docs › library › argparse.html
15.4. argparse — Parser for command-line options, arguments and sub-commands — Editorial Documentation
These can be handled by passing a container object as the choices keyword argument to add_argument(). When the command line is parsed, argument values will be checked, and an error message will be displayed if the argument was not one of the acceptable values: >>> parser = argparse.Argumen...
🌐
ZetCode
zetcode.com › python › argparse
Python argparse - parsing command line arguments in Python with argparse module
September 24, 2024 - #!/usr/bin/python import argparse import datetime import time # choices limits argument values to the # given list parser = argparse.ArgumentParser() parser.add_argument('--now', dest='format', choices=['std', 'iso', 'unix', 'tz'], help="shows datetime in given format") args = parser.parse_args() fmt = args.format if fmt == 'std': print(datetime.date.today()) elif fmt == 'iso': print(datetime.datetime.now().isoformat()) elif fmt == 'unix': print(time.time()) elif fmt == 'tz': print(datetime.datetime.now(datetime.timezone.utc)) In the example, the now option can accept the following values: std, iso, unix, or tz.
Top answer
1 of 2
10

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.

2 of 2
5

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')