An argparse argument can be limited to specific values with the choices parameter:

...
parser.add_argument('--val',
                    choices=['a', 'b', 'c'],
                    help='Special testing value')

args = parser.parse_args(sys.argv[1:])

See the docs for more details.

Answer from Moshe on Stack Overflow
๐ŸŒ
Python
docs.python.org โ€บ 3 โ€บ library โ€บ argparse.html
argparse โ€” Parser for command-line options, arguments and subcommands
ArgumentParser generates the value of dest by taking the first long option string and stripping away the initial -- string. If no long option strings were supplied, dest will be derived from the first short option string by stripping the initial - character. Any internal - characters will be converted to _ characters to make sure the string is a valid attribute name. The examples below illustrate this behavior: >>> parser = argparse.ArgumentParser() >>> parser.add_argument('-f', '--foo-bar', '--foo') >>> parser.add_argument('-x', '-y') >>> parser.parse_args('-f 1 -x 2'.split()) Namespace(foo_bar='1', x='2') >>> parser.parse_args('--foo 1 -y 2'.split()) Namespace(foo_bar='1', x='2')
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
python - How can I pass a list as a command-line argument with argparse? - Stack Overflow
I am trying to pass a list as an argument to a command line program. Is there an argparse option to pass a list as option? parser.add_argument('-l', '--list', type=list, acti... More on stackoverflow.com
๐ŸŒ stackoverflow.com
Python: Argument Parsing Validation Best Practices - Stack Overflow
Python 3.11, I will also test later with 3.7-3.10. The exception raises like with your ValueError example. Since the Action provides the parser instance, I think it's better to use it. 2022-04-07T18:21:13.74Z+00:00 ... Find the answer to your question by asking. Ask question ... See similar questions with these tags. ... Iโ€™m Jody, the Chief Product and Technology Officer at Stack Overflow. Letโ€™s... 0 Argparse ... More on stackoverflow.com
๐ŸŒ stackoverflow.com
Python argparse select a list from choices - Stack Overflow
How do you use argparse to provide a list of arguments from a group of choices. For example, lets say I want something like: python sample.py --p1 ['a','b'] --p2 ['x','y'] Where p1 can only be an... More on stackoverflow.com
๐ŸŒ stackoverflow.com
๐ŸŒ
Brian T. Carr
briancarr.org โ€บ post โ€บ python-validating-argparse-input
Python: Validating Argparse Input with a List
June 3, 2021 - parser = argparse.ArgumentParser() parser.add_argument("-p", "--practice", action="store", type=str, help="Select which practice you want to go to") args = parser.parse_args() The input is then validated with a while loop. First the presence of args.practice was tested with an if statement. if the value was not present, the else clause printed out a warning letting the user know no --practice switch was provided.
๐ŸŒ
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.

๐ŸŒ
Python documentation
docs.python.org โ€บ 3 โ€บ howto โ€บ argparse.html
Argparse Tutorial โ€” Python 3.14.4 documentation
And if you donโ€™t specify the -v flag, that flag is considered to have None value. As should be expected, specifying the long form of the flag, we should get the same output. Sadly, our help output isnโ€™t very informative on the new ability our script has acquired, but that can always be fixed by improving the documentation for our script (e.g. via the help keyword argument). That last output exposes a bug in our program. ... import argparse parser = argparse.ArgumentParser() parser.add_argument("square", type=int, help="display a square of a given number") parser.add_argument("-v", "--verbosity", action="count", help="increase output verbosity") args = parser.parse_args() answer = args.square**2 # bugfix: replace == with >= if args.verbosity >= 2: print(f"the square of {args.square} equals {answer}") elif args.verbosity >= 1: print(f"{args.square}^2 == {answer}") else: print(answer)
๐ŸŒ
Real Python
realpython.com โ€บ command-line-interfaces-python-argparse
Build Command-Line Interfaces With Python's argparse โ€“ Real Python
December 14, 2024 - For example, you may require that a given argument accept an integer value, a list of values, a string, and so on. By default, any argument provided at the command line will be treated as a string. Fortunately, argparse has internal mechanisms to check if a given argument is a valid integer, string, list, and more.
๐ŸŒ
Python Central
pythoncentral.io โ€บ how-to-use-argparse-to-write-command-line-programs-examples-and-tips
How To Use Argparse to Write Command Line Programs: Examples and Tips | Python Central
December 27, 2022 - Sometimes, your app may demand that the supplied argument accept a string, list of values, or another type of value. The command line treats supplied arguments as strings by default. But the argparse module features mechanisms that allow it to check whether an argument is a valid list, string, ...
๐ŸŒ
Flexiple
flexiple.com โ€บ python โ€บ python-argparse-list
Python argparse - Flexiple
March 27, 2024 - import argparse def str_to_coordinate (input_string): x, y = input_string.split(',') return (float(x), float(y)) parser = argparse.ArgumentParser() parser.add_argument('coordinates', type=str_to_coordinate, nargs=2, action='append', help='Pairs of x,y coordinates separated by commas') args = parser.parse_args() coordinate_list = args.coordinates print("List of coordinate pairs received:", coordinate_list) ... The args.coordinates will hold the list [(1.0, 2.0), (3.5, 4.7), (9.2, -1.8)]. Using argparse to work with lists as command-line arguments makes your scripts more versatile and user-friendly. It allows users to provide multiple inputs conveniently, enabling your script to handle complex tasks efficiently! In conclusion, Python argparse is your ultimate companion for handling command-line arguments with ease.
Find elsewhere
Top answer
1 of 13
1688

SHORT ANSWER

Use the nargs option or the 'append' setting of the action option (depending on how you want the user interface to behave).

nargs

parser.add_argument('-l','--list', nargs='+', help='<Required> Set flag', required=True)
# Use like:
# python arg.py -l 1234 2345 3456 4567

nargs='+' takes 1 or more arguments, nargs='*' takes zero or more.

append

parser.add_argument('-l','--list', action='append', help='<Required> Set flag', required=True)
# Use like:
# python arg.py -l 1234 -l 2345 -l 3456 -l 4567

With append you provide the option multiple times to build up the list.

Don't use type=list!!! - There is probably no situation where you would want to use type=list with argparse. Ever.


LONG ANSWER

Let's take a look in more detail at some of the different ways one might try to do this, and the end result.

import argparse

parser = argparse.ArgumentParser()

# By default it will fail with multiple arguments.
parser.add_argument('--default')

# Telling the type to be a list will also fail for multiple arguments,
# but give incorrect results for a single argument.
parser.add_argument('--list-type', type=list)

# This will allow you to provide multiple arguments, but you will get
# a list of lists which is not desired.
parser.add_argument('--list-type-nargs', type=list, nargs='+')

# This is the correct way to handle accepting multiple arguments.
# '+' == 1 or more.
# '*' == 0 or more.
# '?' == 0 or 1.
# An int is an explicit number of arguments to accept.
parser.add_argument('--nargs', nargs='+')

# To make the input integers
parser.add_argument('--nargs-int-type', nargs='+', type=int)

# An alternate way to accept multiple inputs, but you must
# provide the flag once per input. Of course, you can use
# type=int here if you want.
parser.add_argument('--append-action', action='append')

# To show the results of the given option to screen.
for _, value in parser.parse_args()._get_kwargs():
    if value is not None:
        print(value)

Here is the output you can expect:

$ python arg.py --default 1234 2345 3456 4567
...
arg.py: error: unrecognized arguments: 2345 3456 4567

$ python arg.py --list-type 1234 2345 3456 4567
...
arg.py: error: unrecognized arguments: 2345 3456 4567

$ # Quotes won't help here... 
$ python arg.py --list-type "1234 2345 3456 4567"
['1', '2', '3', '4', ' ', '2', '3', '4', '5', ' ', '3', '4', '5', '6', ' ', '4', '5', '6', '7']

$ python arg.py --list-type-nargs 1234 2345 3456 4567
[['1', '2', '3', '4'], ['2', '3', '4', '5'], ['3', '4', '5', '6'], ['4', '5', '6', '7']]

$ python arg.py --nargs 1234 2345 3456 4567
['1234', '2345', '3456', '4567']

$ python arg.py --nargs-int-type 1234 2345 3456 4567
[1234, 2345, 3456, 4567]

$ # Negative numbers are handled perfectly fine out of the box.
$ python arg.py --nargs-int-type -1234 2345 -3456 4567
[-1234, 2345, -3456, 4567]

$ python arg.py --append-action 1234 --append-action 2345 --append-action 3456 --append-action 4567
['1234', '2345', '3456', '4567']

Takeaways:

  • Use nargs or action='append'
    • nargs can be more straightforward from a user perspective, but it can be unintuitive if there are positional arguments because argparse can't tell what should be a positional argument and what belongs to the nargs; if you have positional arguments then action='append' may end up being a better choice.
    • The above is only true if nargs is given '*', '+', or '?'. If you provide an integer number (such as 4) then there will be no problem mixing options with nargs and positional arguments because argparse will know exactly how many values to expect for the option.
  • Don't use quotes on the command line1
  • Don't use type=list, as it will return a list of lists
    • This happens because under the hood argparse uses the value of type to coerce each individual given argument you your chosen type, not the aggregate of all arguments.
    • You can use type=int (or whatever) to get a list of ints (or whatever)

1: I don't mean in general.. I mean using quotes to pass a list to argparse is not what you want.

2 of 13
157

I prefer passing a delimited string which I parse later in the script. The reasons for this are; the list can be of any type int or str, and sometimes using nargs I run into problems if there are multiple optional arguments and positional arguments.

parser = ArgumentParser()
parser.add_argument('-l', '--list', help='delimited list input', type=str)
args = parser.parse_args()
my_list = [int(item) for item in args.list.split(',')]

Then,

python test.py -l "265340,268738,270774,270817" [other arguments]

or,

python test.py -l 265340,268738,270774,270817 [other arguments]

will work fine. The delimiter can be a space, too, which would though enforce quotes around the argument value like in the example in the question.

Or you can use a lambda type as suggested in the comments by Chepner:

parser.add_argument('-l', '--list', help='delimited list input', 
    type=lambda s: [int(item) for item in s.split(',')])
๐ŸŒ
mkaz.blog
mkaz.blog โ€บ working-with-python โ€บ argparse
Parse Command-Line Arguments with Argparse
September 19, 2025 - You can also use the append action to create a list if multiple flags are passed in. parser = argparse.ArgumentParser() parser.add_argument('-c', action='append') args = parser.parse_args() print("~ C: {}".format(args.c)) ... $ python test.py ~ C: None $ python test.py -c hi ~ C: ['hi'] $ python test.py -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.
๐ŸŒ
Medium
medium.com โ€บ @knoldus โ€บ python-argparse-parser-for-command-line-options-arguments-and-sub-commands-ae523a93c4c4
Python Argparse: Parser for command-line options, arguments and sub-commands | by Knoldus Inc. | Medium
March 8, 2021 - All Python data types are valid values of type. ... If it is desired that an argument should value only from a defined list, it is defined as choices parameter. parser.add_argument("sub", choices=['Physics', 'Maths', 'Biology']) To get more ...
๐ŸŒ
Hostman
hostman.com โ€บ tutorials โ€บ command-line option and argument parsing using argparse in python
Master Python argparse: Command-Line Argument Parsing Tutorial
July 21, 2025 - This is useful whenever your program requires a list of values for processing, i.e., numbers, filenames, or options. Here we will show how to use nargs='+' to accept a --numbers option that can take multiple integers. import argparse # Create an ArgumentParser object parser = argparse.ArgumentParser(description="Demonstrating how to handle multiple values using argparse.") # Add the --numbers argument with nargs='+' parser.add_argument('--numbers', nargs='+', type=int, help="List of numbers to process") # Parse the arguments args = parser.parse_args() # Access and display the numbers if args.numbers: print(f"Numbers provided: {args.numbers}") print(f"Sum of numbers: {sum(args.numbers)}") else: print("No numbers provided.
Price ย  $
Call ย  +1 844 286 2130
Address ย  1999 Harrison St 1800 9079, 94612, Oakland
๐ŸŒ
Python Module of the Week
pymotw.com โ€บ 2 โ€บ argparse
argparse โ€“ Command line option and argument parsing. - Python Module of the Week
If the argument allows multiple values, values will be a list even if it only contains one item. The value of option_string also depends on the original argument specifiation. For positional, required, arguments, option_string is always None. $ python argparse_custom_action.py Initializing CustomAction dest = 'a' option_strings = ['-a'] required = False Initializing CustomAction dest = 'm' nargs = '*' option_strings = ['-m'] required = False Initializing CustomAction dest = 'positional' option_strings = [] required = True Processing CustomAction for "a" parser = 4299616464 values = 'value' option_string = '-a' Processing CustomAction for "m" parser = 4299616464 values = ['multi-value'] option_string = '-m' Processing CustomAction for "positional" parser = 4299616464 values = 'positional-value' option_string = None Namespace(a='VALUE', m=['MULTI-VALUE'], positional='POSITIONAL-VALUE')
Top answer
1 of 4
60

The argparse.FileType is a type factory class that can open a file, and of course, in the process raise an error if the file does not exist or cannot be created. You could look at its code to see how to create your own class (or function) to test your inputs.

The argument type parameter is a callable (function, etc) that takes a string, tests it as needed, and converts it (as needed) into the kind of value you want to save to the args namespace. So it can do any kind of testing you want. If the type raises an error, then the parser creates an error message (and usage) and exits.

Now whether that's the right place to do the testing or not depends on your situation. Sometimes opening a file with FileType is fine, but then you have to close it yourself, or wait for the program to end. You can't use that open file in a with open(filename) as f: context. The same could apply to your database. In a complex program you may not want to open or create the file right away.

I wrote for a Python bug/issue a variation on FileType that created a context, an object that could be used in the with context. I also used os tests to check if the file existed or could be created, without actually doing so. But it required further tricks if the file was stdin/out that you don't want to close. Sometimes trying to do things like this in argparse is just more work than it's worth.

Anyways, if you have an easy testing method, you could wrap it in a simple type function like this:

def database(astring):
    from os.path import exists
    if not database_exists(astring):
        raise ValueError  # or TypeError, or `argparse.ArgumentTypeError
    return astring

parser.add_argument('--database', dest='database',
                type = database, 
                default=None, required=False, help='Database to restore')

I don't think it matters a whole lot whether you implement testing like this in the type or Action. I think the type is simpler and more in line with the developer's intentions.

2 of 4
29

Surely! You just have to specify a custom action as a class, and override __call__(..). Link to documentation.

Something like:

import argparse

class FooAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        if values != "bar":
            print("Got value:", values)
            raise ValueError("Not a bar!")
        setattr(namespace, self.dest, values)


parser = argparse.ArgumentParser()
parser.add_argument("--foo", action=FooAction)

parsed_args = parser.parse_args()

In your particular case, I imagine you'd have DatabaseAction and FileAction (or something like that).

๐ŸŒ
Mimo
mimo.org โ€บ glossary โ€บ python โ€บ argparse
Python argparse: Syntax, Usage, and Examples
Use the const keyword when you ... specific value with a flag: ... This sets args.reset to 0 when --reset is provided. You can also pair this with nargs to create toggle-style arguments. A python argparse add_argument const scenario often arises when mapping specific flags to predefined configurations. You can combine nargs with custom types to parse and validate user input: ... Now args.ids is ['1', '2', '3']. This approach lets you handle python argparse list inputs without ...
๐ŸŒ
ZetCode
zetcode.com โ€บ python โ€บ argparse
Python argparse - parsing command line arguments in Python with argparse module
September 24, 2024 - In the example, the now option can accept the following values: std, iso, unix, or tz. $ ./mytime.py --now iso 2022-08-20T09:44:22.437880 $ ./mytime.py --now unix 1660981466.8261166 ยท The following example mimics the Linux head command. It shows the n lines of a text from the beginning of the file. ... For the example, we have this small test file. ... #!/usr/bin/python import argparse from pathlib import Path # head command # working with positional arguments parser = argparse.ArgumentParser() parser.add_argument('f', type=str, help='file name') parser.add_argument('n', type=int, help='show n lines from the top') args = parser.parse_args() filename = args.f lines = Path(filename).read_text().splitlines() for line in lines[:args.n]: print(line)
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')
๐ŸŒ
Kodeclik
kodeclik.com โ€บ python-argumentparser-list
Passing a list as a command-line argument to Python
September 24, 2024 - This is useful when the script requires a specific number of arguments for an option. Finally, nargs="?" indicates that the option can take zero or one value but not more values. So in summary, the argparse module in Python provides a robust and user-friendly way to handle different types of arguments, including lists.
๐ŸŒ
Towards Data Science
towardsdatascience.com โ€บ home โ€บ latest โ€บ a simple guide to command line arguments with argparse
A Simple Guide To Command Line Arguments With ArgParse | Towards Data Science
January 21, 2025 - The standard Python library argparse used to incorporate the parsing of command line arguments. Instead of having to manually set variables inside of the code, argparse can be used to add flexibility and reusability to your code by allowing user input values to be parsed and utilized.