Search code examples
pythonargparse

Python argparse - make arguments required or optional based on another argument


How can a program accept/validate a set of parameters, depending on a previous parameter/option?

e.g:

params:
        <action1> -p <path>  -name <name> -t <type>
        <action2> -v <value> -name <name>
        <action3> -p <path> -t <type>
        <action4> -m <mode1 | mode2>
        --verbose
        --test
        --..

So if one of the actionX parameters is used (only one can be used), additional parameters might be required. For instance for action2 the -v and -name are required.

valid input:

python myparser.py action2 -v 11 -name something --test --verbose
python myparser.py action4 -m mode1 
python myparser.py --test 

invalid input:

python myparser.py action2 -v 11 
python myparser.py action4 -n name1

Can the argparse validate this or is it better to add all of them as optional and validate them later on?


Solution

  • You can use subparsers

    Simple example for your case

    from argparse import ArgumentParser
    
    parser = ArgumentParser()
    parser.add_argument("--test", action="store_true")
    subparsers = parser.add_subparsers()
    
    parser_action2 = subparsers.add_parser("action2")
    parser_action2.add_argument("-v", required=True)
    parser_action2.add_argument("-name", type=str, required=True)
    
    parser_action4 = subparsers.add_parser("action4")
    parser_action4.add_argument("-m", type=str, required=True)
    

    valid case

    parser.parse_args(["action2", "-v", "11", "-name", "something"])
    parser.parse_args(["action4", "-m", "mode1"])
    parser.parse_args(["--test"])
    
    # Namespace(v='11', name='something')
    # Namespace(m='mode1')
    # Namespace(test=True)
    

    Invalid case

    parser.parse_args(["action2", "-v", "11"])
    # action2: error: the following arguments are required: -name
    
    parser.parse_args(["action4", "-n", "name1"])
    # action4: error: the following arguments are required: -m
    

    EDIT: And in case you want to use shared argument which is required in one and optional in others, it is better to make them optional and validate them later as you said.