Python argparse: Mutually exclusive required group with a required option

14,690

You have already achieved it! Argparse only prints the first error it finds, so while it may look like it's only checking -k, it actually recuires -n/-t too. You can see this by actually giving it the -k argument.

If you provide the -k argument, the error message will change from test.py: error: argument -k/--kick_start is required to test.py: error: one of the arguments -n/--name -t/--template is required.

Share:
14,690

Related videos on Youtube

Abhinav
Author by

Abhinav

Updated on June 03, 2022

Comments

  • Abhinav
    Abhinav almost 2 years

    I am trying to have a required mutually exclusive group with one required parameter. Below is the code which I have put

    #!/usr/bin/python
    
    import argparse
    import sys
    
    # Check for the option provided as part of arguments
    def parseArgv():
        parser = argparse.ArgumentParser()
        group = parser.add_mutually_exclusive_group()
        group.add_argument("-v", "--verbose", choices=[1,2,3,4],
                help = "Increase verbosity")
        group.add_argument("-q", "--quiet", action="store_true", help = "Run quietly")
        name = parser.add_mutually_exclusive_group(required=True)
        name.add_argument("-n", "--name", help = "Name of the virtual machine")
        name.add_argument("-t", "--template", help = "Name of the template to use \
                for creating vm. If path is not provided then it will be looked \
                under template directory.")
        parser.add_argument("-s", "--save", help = "Save the machine template. If \
                path is not provided then it will be saved under template directory.");
        #parser.add_argument("-k", "--kick_start", required = True, help = "Name of the \
        #        kick start file. If path is not provided then it will be look into http \
        #        directory.")
        if len(sys.argv) == 1:
            parser.print_help()
        args = parser.parse_args()
    
    if __name__ == '__main__':
        parseArgv()
    

    Now the output of this program as follow

    $ python test.py 
    usage: test.py [-h] [-v {1,2,3,4} | -q] (-n NAME | -t TEMPLATE) [-s SAVE]
    
    optional arguments:
      -h, --help            show this help message and exit
      -v {1,2,3,4}, --verbose {1,2,3,4}
                            Increase verbosity
      -q, --quiet           Run quietly
      -n NAME, --name NAME  Name of the virtual machine
      -t TEMPLATE, --template TEMPLATE
                            Name of the template to use for creating vm. If path
                            is not provided then it will be looked under template
                            directory.
      -s SAVE, --save SAVE  Save the machine template. If path is not provided
                            then it will be saved under template directory.
    usage: test.py [-h] [-v {1,2,3,4} | -q] (-n NAME | -t TEMPLATE) [-s SAVE]
    test.py: error: one of the arguments -n/--name -t/--template is required
    

    But if I un-comment the from line 20 - 22 then the output change as below

    $ python test.py 
    usage: test.py [-h] [-v {1,2,3,4} | -q] (-n NAME | -t TEMPLATE) [-s SAVE] -k
                   KICK_START
    
    optional arguments:
      -h, --help            show this help message and exit
      -v {1,2,3,4}, --verbose {1,2,3,4}
                            Increase verbosity
      -q, --quiet           Run quietly
      -n NAME, --name NAME  Name of the virtual machine
      -t TEMPLATE, --template TEMPLATE
                            Name of the template to use for creating vm. If path
                            is not provided then it will be looked under template
                            directory.
      -s SAVE, --save SAVE  Save the machine template. If path is not provided
                            then it will be saved under template directory.
      -k KICK_START, --kick_start KICK_START
                            Name of the kick start file. If path is not provided
                            then it will be look into http directory.
    usage: test.py [-h] [-v {1,2,3,4} | -q] (-n NAME | -t TEMPLATE) [-s SAVE] -k
                   KICK_START
    test.py: error: argument -k/--kick_start is required
    

    But I want that either -n / -t along with -k become mandatory. How to achieve the same.

  • Abhinav
    Abhinav almost 10 years
    Thanks, I was not knowing it as I am learning Python :). One more thing how to check if argument has some value. Is there some empty(C++) like function.
  • Aleksi Torhamo
    Aleksi Torhamo almost 10 years
    You should really ask a separate question if it isn't related (after checking it hasn't been asked already, of course), but... It depends on what exactly you want to do. Python has a concept of "truthiness", so you can just use the variable directly in an if-clause or whatever, eg. if variable: or if not variable:. Aside from that, you can use eg. len(variable) == 0 on containers or variable is None to check that it is None specifically. Or just compare to the empty value for the type in question.
  • hpaulj
    hpaulj almost 10 years
    The default value for your argparse arguments is None. Thus print args.name is None will print True. Default for args.quiet is False.