How to have different mandatory parameters for two categories using argparse python?

Viewed 123

I am working on python script where I need to do two things basis on the input parameters passed:

  • push: This will call an api to post some data.
  • status: This will call another api to check the data and print out details on the console.

When we use push parameter then we need to always pass these three mandatory parameters:

  • environment
  • instance
  • config

And when we use status parameter then we need to pass only these two mandatory parameters:

  • environment
  • instance

How can I make these arguments configurable in such a way using argparse in Python? I was reading more about this here but confuse on how to make above things work in nice way? Also usage message should clearly tell what to use with what input.

Is this possible to do using argparse? Any example will be greatly appreciated. In general we will call a method for push case which will use those parameters and similarly for status we will call some other method which will use those parameters.

3 Answers

You could do something like this, using set_defaults to attribute a handler for each subcommand.

import argparse

def push(args):
    return (args.environment, args.instance, args.config)

def status(args):
    return (args.environment, args.instance)

parser = argparse.ArgumentParser()

subparsers = parser.add_subparsers()

# create the parser for the push command
push_parser = subparsers.add_parser('push')
push_parser.set_defaults(func=push)

push_parser.add_argument('--environment', type=str)
push_parser.add_argument('--instance', type=str)
push_parser.add_argument('--config', type=str)


# create the parser for the status command
status_parser = subparsers.add_parser('status')
status_parser.set_defaults(func=status)

status_parser.add_argument('--environment', type=str)
status_parser.add_argument('--instance', type=str)

    
args = parser.parse_args(['push', '--environment=a', '--instance=b', '--config=c'])
print(args.func(args))

Here's a simple example that uses argparse with two subcommands:

"""
How to have different mandatory parameters for two categories
using argparse python?
"""
import argparse
import sys

def main():
    """
    Description here
    """
    parser = argparse.ArgumentParser(
        description='Stack Overflow 64995368 Parser'
    )
    parser.add_argument(
        "-v",
        "--verbose",
        help="verbose output",
        action="store_true"
    )
    subparser = parser.add_subparsers(
        title="action",
        dest='action',
        required=True,
        help='action sub-command help'
    )

    # create the subparser for the "push" command
    parser_push = subparser.add_parser(
        'push',
        help='push help'
    )
    parser_push.add_argument(
        'environment',
        type=str,
        help='push environment help'
    )
    parser_push.add_argument(
        'instance',
        type=str,
        help='push instance help'
    )
    parser_push.add_argument(
        'config',
        type=str,
        help='push config help'
    )

    # create the subparser for the "status" command
    parser_status = subparser.add_parser(
        'status',
        help='status help'
    )
    parser_status.add_argument(
        'environment',
        type=str,
        help='status environment help'
    )
    parser_status.add_argument(
        'instance',
        type=str,
        help='status instance help'
    )

    args = parser.parse_args()

    if args.action == 'push':
        print('You chose push:',
            args.environment, args.instance, args.config)
    elif args.action == 'status':
        print('You chose status:',
            args.environment, args.instance)
    else:
        print('Something unexpected happened')

if __name__ == "__main__":
    try:
        sys.exit(main())
    except KeyboardInterrupt:
        print("\nCaught ctrl+c, exiting")

Example output for various command lines:

$ python3 test.py
usage: test.py [-h] [-v] {push,status} ...
test.py: error: the following arguments are required: action

$ python3 test.py -h
usage: test.py [-h] [-v] {push,status} ...

Stack Overflow 64995368 Parser

optional arguments:
  -h, --help     show this help message and exit
  -v, --verbose  verbose output

action:
  {push,status}  action sub-command help
    push         push help
    status       status help

$ python3 test.py push -h
usage: test.py push [-h] environment instance config

positional arguments:
  environment  push environment help
  instance     push instance help
  config       push config help

optional arguments:
  -h, --help   show this help message and exit

$ python3 test.py push
usage: test.py push [-h] environment instance config
test.py push: error: the following arguments are required: environment, instance, config

$ python3 test.py push myenv
usage: test.py push [-h] environment instance config
test.py push: error: the following arguments are required: instance, config

It's often easier just to use sys.argv contents directly. https://www.tutorialspoint.com/python/python_command_line_arguments.htm

#! /usr/bin/env python3

import sys
s_args  = sys .argv  ##  s_args[0] = script_name.py

def push( environment,  instance,  config ):
    print( 'PUSH command:',  environment,  instance,  config )

def status( environment,  instance ):
    print( 'STATUS command:',  environment,  instance )

##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

if __name__ == '__main__':
    if len( s_args ) < 4:
        print( 'missing args:' )
        print( '    PUSH environment instance config' )
        print( '    STATUS environment instance' )

    elif s_args[1] .lower() == 'push':
        if len( s_args ) < 5:
            print( 'missing args for PUSH command:' )
            print( '    PUSH environment instance config' )
        else:
            push( s_args[2],  s_args[3],  s_args[4] )

    elif s_args[1] .lower() == 'status':
        if len( s_args ) < 4:
            print( 'missing args for STATUS command:' )
            print( '    STATUS environment instance' )
        else:
            status( s_args[2],  s_args[3] )

    else:
        print( 'incorrect command:' )
        print( '    PUSH environment instance config' )
        print( '    STATUS environment instance' )
Related