Argparse notes
From raju
create parser
import argparse def create_parser(): parser = argparse.ArgumentParser(description='Get list of elements') parser.add_argument('elements', nargs='+', help="list of elements") return parser if __name__ == '__main__': parser = create_parser() args = parser.parse_args()
- http://dustinrcollins.com/testing-python-command-line-apps - shows how to test command line python apps. Notice how he breaks up the code. The function create_parser() only initializes the parser and adds arguments. The actual parsing is done after calling the create_parser() function. This way we can use create_parser() in unit tests and modify it as needed.
only allow some values for a positional argument
useful links
pass list
You can either use the nargs option or the 'append' setting of the action option (depending on how you want the user interface to behave).
nargs='+' takes 1 or more arguments, nargs='*' takes zero or more.
UI with nargs: -l val1 val2 val3 parser.add_argument('-l', '--my-list', nargs='+', help='Required list of items', required=True)
UI with action='append': -l val1 -l val2 -l val3 parser.add_argument('-l', '--my-list', action='append', help='Required list of items', required=True)
UI with mandatory args: val1 val2 val3 # 'required' option should not used for mandatory arguments. parser.add_argument('elements', nargs='+', help='List of elements')
All options are converted to strings.
Sample code:- https://github.com/KamarajuKusumanchi/sampleusage/blob/master/python/pass_list.py
Introduction
For parsing command line arguments in Python use argparse. Do not use optparse (which is deprecated) or getopt (which involves writing more code).
- Tutorial on argparse - https://docs.python.org/3.3/howto/argparse.html#id1
- Self contained python3 code that involves argument parsing, classes, unit tests and regression tests - Python_code_templates#Template1
- Using argparse module in practice - make_bkup.py, time_calc.py, scottrade.py, git_grep.py
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"}'
--feature and --no-feature
all positional arguments into a list
parser.add_argument( 'input_files', nargs='*', action='store', help='list of input files'
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
- See if the solution listed in https://stackoverflow.com/a/9398245/6305733 can be used to test argparse functionality in a simple but generic way.
convert input from string to integer
parser.add_argument( '--daily-history', dest='daily_history', default=30, type=int, help='number of daily output files to be preserved. Default = 30' )