pythonargparsesubparsers

How to use sub-commands along with optional positional arguments in argparse


Below scripts prints an output as well as opens a webpage based on command line arguments.

#main.py

import os, numpy
import argparse
import webbrowser

new=2

def main():
    parser = argparse.ArgumentParser() 
    parser.add_argument('-i','--input',type=str, help='Choose input')
    parser.add_argument('-d','--display',dest='disp',type=str, help='Opens a webpage', default=None)

    args = parser.parse_args()
 
    if args.input == 'infile':
        print('This is input file')

    if args.disp == 'openbrowser':
        url = "https://stackoverflow.com/"
        webbrowser.open(url,new=new,autoraise=True)
     
if __name__=='__main__':
    main()

If I use the following command:

python3 main.py --input infile --display openbrowser

The desired output is attained. But, I would like --display (ideally without any str) to be parsed along with --input as a sub-command and not as a separate optional flag argument -d. The flag -display is only used if --input is used as the primary flag, and even --display should be optional in itself and shouldn't be obligatory.

So I would like the command line arguments to look like:

python3 main.py --input infile --display

This prints This is input file and opens webpage in the browser. and

python3 main.py --input infile 

This prints the output This is input file only


Solution

  • You're looking for the action='store_true' property on the argument specification. https://docs.python.org/3/library/argparse.html#action

    parser.add_argument('-d', '--display', dest='disp',
                        action='store_true', help='Opens a webpage')
    
    #main.py
    
    import os, numpy
    import argparse
    import webbrowser
    
    new=2
    
    def main():
        parser = argparse.ArgumentParser()
        parser.add_argument('-i','--input',type=str, help='Choose input')
        parser.add_argument('-d','--display',dest='disp', action='store_true', help='Opens a webpage')
    
        args = parser.parse_args()
    
        if args.input == 'infile':
            print('This is input file')
    
        if args.disp:
            url = "https://stackoverflow.com/"
            webbrowser.open(url,new=new,autoraise=True)
    
    if __name__=='__main__':
        main()