Search code examples
pythonargparse

argparse: how to configure multiple choice, multiple value, optional argument?


I'm trying to set up an argument that accepts one or more values from a given list of choices, but is not obligatory. I'm trying this (with a couple of variants that also don't work as expected):

parser.add_argument("FLAGS", nargs='*', choices=["X","Y","Z","ALL"])

I expect to get a list of values from the list of choices, or an empty list if nothing was given (that, I think, should be enforced by nargs='*'). But regardless of whether I add default="" or not, when I don't pass any argument it fails with:

error: argument FLAGS: invalid choice: []

How to achieve what I need?


Solution

  • This probably doesn't fit your needs, but you can do it easily with an option like --flags.

    parser.add_argument(
        "--flags",
        nargs='*',
        default=[],  # Instead of "None"
        choices=["X", "Y", "Z", "ALL"])
    
    args = parser.parse_args()
    print(args)
    
    $ tmp.py
    Namespace(flags=[])
    
    $ tmp.py --flags
    Namespace(flags=[])
    
    $ tmp.py --flags X
    Namespace(flags=['X'])
    
    $ tmp.py --flags X Z
    Namespace(flags=['X', 'Z'])
    
    $ tmp.py --flags foobar
    usage: tmp.py [-h] [--flags [{X,Y,Z,ALL} ...]]
    tmp.py: error: argument --flags: invalid choice: 'foobar' (choose from 'X', 'Y', 'Z', 'ALL')
    
    $ tmp.py --help
    usage: tmp.py [-h] [--flags [{X,Y,Z,ALL} ...]]
    
    optional arguments:
      -h, --help            show this help message and exit
      --flags [{X,Y,Z,ALL} ...]