How do I configure a python argparse
object to accept an optional argument multiple times, similar to how I can pass --exclude
to grep
mutliple times?
# Command line example
python main.py --exclude=foo.js --exclude=bar.java # args.exclude should be ['foo.js', 'bar.java']
python main.py --exclude=foo.js # args.exclude should be ['foo.js']
python main.py # args.exclude should be []
python main.py --exclude foo.js bar.java # Reject this, or don't put bar.java in list
python main.py --exclude # Reject this
I tried this code, but it only accepts the last --exclude
argument. The previous ones are discarded.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument( '--exclude', type=str, nargs='*', default=[], help='Something to exclude')
args = parser.parse_args('--exclude=foo.js --exclude=bar.java'.split(' '))
print(args.exclude)
# output
['bar.java'] # actual output
['foo.js', 'bar.java'] # desired output
Additional requirements
--exclude
should be optional. args.exclude
should be an empty list if exclude isn't supplied--exclude
is supplied, it should have 1 and only 1 argument.I get the exact behavior I want in python 3.11 by omitting the nargs
argument, and adding action='append'
. Here is a complete test app
import argparse
parser = argparse.ArgumentParser()
parser.add_argument( '--exclude', type=str, action='append', default=[], help='Something to exclude')
test_inputs = [
'--exclude=foo.js --exclude=bar.java',
'',
'--exclude=foo.js bar.java',
'--exclude'
]
for cmdline in test_inputs:
print(f'"{cmdline}" parsed as : ', end='', flush=True)
args = parser.parse_args(cmdline.split(' ') if cmdline else [])
print (args.exclude, flush=True)
# output
"--exclude=foo.js --exclude=bar.java" parsed as : ['foo.js', 'bar.java']
"" parsed as : []
"--exclude=foo.js bar.java" parsed as : usage: main.py [-h] [--exclude EXCLUDE]
main.py: error: unrecognized arguments: bar.java
"--exclude" parsed as : usage: main.py [-h] [--exclude EXCLUDE]
main.py: error: argument --exclude: expected one argument
Note that if you run this, the app actually aborts after the first parse error. You have to comment out that input to see the last error.