Search code examples
pythonargparse

Python argparse: How to make an initial parameter determine how many parameters come after?


I'd like to do the following, where the type specified dictates what parameters I can use after.

For example, for cmd1, I'd expect a param1 and param2.

For cmd2, I'd expect a param3, param4, param5, and param6.

For cmd3, I'd expect no parameters.

If I don't specify the expected parameters, an error should be shown.


Also, is there someway I could make it so that issuing a -h would show the different combinations allowed?

In all situations, there may be other tags that could be specified, such as --id 5 or --config 1.

Is this possible with python's argparse?

I.e.,

python test.py --type cmd1 param1 param2 --id 5

python test.py --config 2 --type cmd2 param3 param4 param5 param6

python test.py --type cmd3 --config 1

Solution

  • This use of subcommands will get most of what you want. Read the docs for explainations

    #python test.py --type cmd1 param1 param2 --id 5
    #python test.py --config 2 --type cmd2 param3 param4 param5 param6
    #python test.py --type cmd3 --config 1
    
    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument('--config', type=int)
    parser.add_argument('--id', type=int)
    sp = parser.add_subparsers(dest='type', required=True)
    sp1 = sp.add_parser('cmd1')
    sp1.add_argument('param1')
    sp1.add_argument('param2')
    sp2 = sp.add_parser('cmd2')
    sp2.add_argument('parame1')
    # etc
    sp3 = sp.add_parser('cmd3')
    
    args = parser.parse_args()
    print(args)
    

    test cases

    1535:~/mypy$ python3 stack70763135.py -h
    usage: stack70763135.py [-h] [--config CONFIG] [--id ID] {cmd1,cmd2,cmd3} ...
    
    positional arguments:
      {cmd1,cmd2,cmd3}
    
    optional arguments:
      -h, --help        show this help message and exit
      --config CONFIG
      --id ID
    
    1535:~/mypy$ python3 stack70763135.py --id 5 cmd1 foo1 foo2
    Namespace(config=None, id=5, param1='foo1', param2='foo2', type='cmd1')
    1535:~/mypy$ python3 stack70763135.py --config 2 cmd2 foo1
    Namespace(config=2, id=None, parame1='foo1', type='cmd2')
    1536:~/mypy$ python3 stack70763135.py --config 3 cmd3
    Namespace(config=3, id=None, type='cmd3')
    

    The help's might be more fragmented that what you want, but the info is all there.

    id and config have to come before the cmd entries.