Python 2.7 - Argparse Usage

bsumariwalla
bsumariwalla used Ask the Experts™
on
Hello,

I'm using Python 2.7 and the Argparse module to parse command line parameters.    I have the following stripped down code, but I'd like to use subparsers and parents to make the help more obvious.   I have the following usage cases that I am trying to accommodate, but I can't figure out how to do this properly with subparsers.  If someone could nudge me in the right direction with a couple of generic examples, I would appreciate it.  

script.py # script should execute and assume the -i switch
script.py -i # script should execute in interactive mode
script.py -f [fname] # The script should execute in file mode.  The script takes fname as a parameter and executes.  In my code below, I have the fname validated via another function, but I can't figure that out with subparsers
script.py -E [endpoint] -s [start_time] -e [end_time] # The script executes in endpoint mode.   The -s is mandatory with -E  and -e is optional.   However, if parameters are passed they must be validated with the valid_date function.  I have this working in the code below, but I can't figure it out with subparsers.   I may at some point also try to validate the endpoint parameter.

"-a" and "-x" are optional parameters and may be used with any of the three modes listed above.   I know this is accomplished via parents.  However, I can't get this working the closest I've come is code that doesn't error out.  However, --help does not display existence of the switches either.


import argparse
from time import time as timer
import sys
def valid_date(iso8601):
    pass
def valid_file(parser, fname):
    pass
    return fname
def file_mode(fname, audit, staging):
    print("Start in file mode.  Audit is {} and staging is {}.".format(audit, staging))
    sys.exit(0)
def endpoint_mode(endpoint, start_time, end_time, audit, staging):
    print("Start in endpoint mode.  Audit is {} and staging is {}.".format(audit, staging))
    sys.exit(0)
def interactive_mode(audit, staging):
    print("Start in interactive mode.  Audit is {} and staging is {}.".format(audit, staging))
def main():
    parser = argparse.ArgumentParser(description="This is my test ArgParse script.")
    group = parser.add_mutually_exclusive_group()
    
    group.add_argument("-i", \
                        dest="interactive", \
                        action="store_true", \
                        help="Run the script interactively.  This is the default " + \
                             "mode if no options are specfied.")
    group.add_argument("-f", \
                        dest="fname", \
                        help="Run the script against an input file.", \
                        metavar="FILE", \
                        type=lambda x: valid_file(parser, x))
    group.add_argument("-E", \
                        dest="endpoint",
                        help="Run the script against a specific endpoint.",
                        metavar="ENDPOINT")
    parser.add_argument("-a", \
                        dest="audit", \
                        action="store_true", \
                        help="Audit only.")
    parser.add_argument("-x", \
                        dest="staging", \
                        action="store_true", \
                        help="Switches queries to use staging.")
    parser.add_argument("-s", \
                        dest="start_time", \
                        help="Specify a start date.  This is mandatory with the -E switch.", \
                        metavar="DATE",
                        type=valid_date)
    parser.add_argument("-e", \
                        dest="end_time", \
                        help="Specify an end date.  This optional with the -E switch.", \
                        metavar="DATE")
    args = parser.parse_args()
    audit = args.audit
    staging = args.staging
    interactive = args.interactive
    fname = args.fname
    endpoint = args.endpoint
    start_time = args.start_time
    end_time = args.end_time
    if not len(sys.argv) > 1:
        interactive_mode(audit, staging)
    if args.interactive is True:
        interactive_mode(audit, staging)
    if '-f' in sys.argv:
        file_mode(fname, audit, staging)
    if '-E' in sys.argv:
        endpoint_mode(endpoint, start_time, end_time, audit, staging)
     

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Have you seen docopt? Until now, I haven't seen this myself but I am glad I did now.
You'll have to explicitly do the argument-validation yourself but it gets most of what I understand of your requirements.
"""Usage: prog [-a] [-x]
          prog ( -i | -f FNAME | -E ENDPOINT -s START_TIME [-e END_TIME] ) [-a] [-x]

Process FILE and optionally apply correction to either left-hand side or
right-hand side.

Arguments:
  FNAME         must be validated by another function
  ENDPOINT      The -s is mandatory with -E  and -e is optional.
  START_TIME    If passed, must be validated with the valid_date function
  END_TIME      ditto

Options:
  -h --help
  -i        script should execute in interactive mode
  -f        script should execute in file mode
  -E        script executes in endpoint mode
  -a        Audit only 
  -x        use staging

"""
from docopt import docopt


if __name__ == '__main__':
    d = docopt(__doc__)  # parse arguments based on docstring above
    print d

Open in new window


testing:
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\>python docopttest.py
{'-E': False,
 '-a': False,
 '-e': False,
 '-f': False,
 '-i': False,
 '-s': False,
 '-x': False,
 'ENDPOINT': None,
 'END_TIME': None,
 'FNAME': None,
 'START_TIME': None}

C:\>python docopttest.py -i
{'-E': False,
 '-a': False,
 '-e': False,
 '-f': False,
 '-i': True,
 '-s': False,
 '-x': False,
 'ENDPOINT': None,
 'END_TIME': None,
 'FNAME': None,
 'START_TIME': None}

C:\>python docopttest.py -i -a -z
Usage: prog [-a] [-x]
          prog ( -i | -f FNAME | -E ENDPOINT -s START_TIME [-e END_TIME] ) [-a] [-x]

C:\>python docopttest.py -i -a -x
{'-E': False,
 '-a': True,
 '-e': False,
 '-f': False,
 '-i': True,
 '-s': False,
 '-x': True,
 'ENDPOINT': None,
 'END_TIME': None,
 'FNAME': None,
 'START_TIME': None}

C:\>python docopttest.py -f
Usage: prog [-a] [-x]
          prog ( -i | -f FNAME | -E ENDPOINT -s START_TIME [-e END_TIME] ) [-a] [-x]

C:\>python docopttest.py -f foo.bar
{'-E': False,
 '-a': False,
 '-e': False,
 '-f': True,
 '-i': False,
 '-s': False,
 '-x': False,
 'ENDPOINT': None,
 'END_TIME': None,
 'FNAME': 'foo.bar',
 'START_TIME': None}

C:\>python docopttest.py -E EP_here
Usage: prog [-a] [-x]
          prog ( -i | -f FNAME | -E ENDPOINT -s START_TIME [-e END_TIME] ) [-a] [-x]

C:\>python docopttest.py -E EP_here -s 2017-01-01
{'-E': True,
 '-a': False,
 '-e': False,
 '-f': False,
 '-i': False,
 '-s': True,
 '-x': False,
 'ENDPOINT': 'EP_here',
 'END_TIME': None,
 'FNAME': None,
 'START_TIME': '2017-01-01'}

C:\>python docopttest.py -E EP_here -s 2017-01-01 -x
{'-E': True,
 '-a': False,
 '-e': False,
 '-f': False,
 '-i': False,
 '-s': True,
 '-x': True,
 'ENDPOINT': 'EP_here',
 'END_TIME': None,
 'FNAME': None,
 'START_TIME': '2017-01-01'}

C:\>python docopttest.py -E EP_here -s 2017-01-01 -e 2017-10-01
{'-E': True,
 '-a': False,
 '-e': True,
 '-f': False,
 '-i': False,
 '-s': True,
 '-x': False,
 'ENDPOINT': 'EP_here',
 'END_TIME': '2017-10-01',
 'FNAME': None,
 'START_TIME': '2017-01-01'}

Open in new window

Question inactive

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial