Argparse notes

From raju

Introduction

For parsing command line arguments in Python use argparse. Do not use optparse (which is deprecated) or getopt (which involves writing more code).

parse and validate

tags| fail if an option's value is not specified

def parse_arguments(args):
    import argparse
    parser = argparse.ArgumentParser(
        description='Get input'
        )
    parser.add_argument(
        "--foo", action='store',
        dest='foo',
        help='User must specify a value for foo on the command line.')
    parser.add_argument(
        "--debug", action='store_true',
        default=False, dest='debug',
        help='show debug output. Default is false.')

    res = parser.parse_args(args)
    if res.debug:
        print(res)
    return res

def validate_arguments(args):
    foo = args.foo
    if (foo is None):
        print("Error: foo is not specified. Please specify one.")
        raise()

if __name__ == "__main__":
    args = parse_arguments(sys.argv[1:])
    validate_arguments(args)

Sample usage of argparse

    import argparse
    import textwrap  # for dedent

    parser = argparse.ArgumentParser(
        description='Explain what the script does')

    # Description spanning across multiple lines
    parser = argparse.ArgumentParser(
        description='''Utility script that tells why a given set of packages
        are installed.''')

    # preformatted description and epilog
    parser = argparse.ArgumentParser(
        description='My super duper space probe',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog=textwrap.dedent('''\
        Features:
        * Ability to orbit Jupiter
        * Ability to scratch Sun
        '''))


    # mandatory positional argument
    parser.add_argument(
        "pattern", action="store",
        help="pattern to search for")

    # optional positional argument
    parser.add_argument(
        "dir", nargs='?',
        default=os.getcwd(),
        help="directory")

    # optional argument that has a default value
    parser.add_argument(
        "--out_dir", default='~/scratch',
        help="output directory name")

    parser.add_argument("--dry", action="store_true",
        default=False, dest="dry",
        help="perform a trial run with no actual changes")
    parser.add_argument("--debug", action="store_true",
        default=False, dest="debug",
        help="show debug output")

    args = parser.parse_args()

pass dictionary

import json
parser.add_argument('-d', '--my_dict', type=json.loads)
args = parse.parse_args()

mydict = args.my_dict  # Will return a dictionary

Call the script as

<script> --my_dict '{"value1":"key1"}'

Ref:- http://stackoverflow.com/questions/18608812/accepting-a-dictionary-as-an-argument-with-argparse-and-python

--feature and --no-feature

    parser.add_argument(
        "--header", action='store_true',
        dest='header',
        help='use 1st line as header')
    parser.add_argument(
        "--no-header", action='store_false',
        dest='header',
        help='assumes that there is no header')
    parser.set_defaults(header=True)

all positional arguments into a list

    parser.add_argument(
        'input_files', nargs='*',
        action='store',
        help='list of input files'

only allow some values for a positional argument

    parser.add_argument("access", action='store',
        choices=['allow', 'deny'], help='type of access')

show default values in the help page

There are two ways to achieve this

Specify the formatter_class parameter when initializing the parser.

    parser = argparse.ArgumentParser(
        description='''Do something.
        ''',
        formatter_class=argparse.ArgumentDefaultsHelpFormatter
    )

Ref:- https://docs.python.org/3/library/argparse.html#argparse.ArgumentDefaultsHelpFormatter

or add '%(default)' in the help string and include the variable 'type' in the formatting string -- e.g. '%(default)s' for a string, or '%(default)d' for a digit.

    parser.add_argument(
        '--out-dir',
        default='C:\Temp\output',
        help='Output directory. Default = %(default)s'
    )

Ref:- https://stackoverflow.com/a/18507871/6305733

raise incompatible argument error

def validate_options(args):
    if any(v is None for v in [args.old_date, args.new_date]) and \
            any(v is None for v in [args.old_dir, args.new_dir]):
        raise ValueError('Incompatible arguments. Either specify --old-date '
                         'and --new_date or --old-dir and --new-dir.\n'
                         'Specified values are:\n {}'.format(args))

check later