argparse and subparsers

Sachin Garg s.garg.computer at gmail.com
Mon Jun 27 00:55:57 EDT 2016


On Sunday 26 June 2016 02:51 PM, Joseph L. Casale wrote:
> I have some code where sys.argv is sliced up and manually fed to discrete argparse
> instances each with a single subparser. The reason the discrete parsers all having a
> single subparser was to make handling the input simpler, the first arg in the slice
> could be left in.
> 
> This has become unmaintainable as the manual slicing is always subject to a new case
> by where a parser has a positional, switch or optional parameter for example. Also, since
> argv is grouped by subparser specifiers, if a parameter has input that matches a keyword
> it all goes pear shaped.
> 
> The underlying root of this mess is a long unaddressed limitation in argparse to support
> multiple subparser specifications on the same invocation:
> 
> prog.py -x -y 42 -foo bar subParserA -a 1 -b 2 subParserB -a 1 -b 2 subParserB -a 1 -b 2
> 
> The base arguments (-x -y 42 -foo bar).
> An invocation of "subParserA" and its arguments (-a 1 -b 2).
> Two invocations of "subParserB" and their arguments.
> 
> etc...
> 
> I have seen some creative ways to overcome this on stacktrace, however I thought I'd
> see what people here have done. The code is pinned at 2.7 and while several people
> have created alternate implementations which address many of argparses failures, its
> desired to stick to base lib but that can easily be changed given a compelling reason
> if an alternate implementation exists that works well.


Not sure if this fits the bill, or makes sense here, but I came cross
"docopt" which touts itself as a "Command-line interface description
language". I used it in a project and it seems to be pretty easy to use
as well as elegant. It stores the arguments & values as a dictionary,
keyed by the argument.

from docopt import docopt

arguments = docopt(__doc__, version='0.2')

# Set verbose flag
verbose = False
if arguments['--verbose']:
    verbose = True
elif arguments['-q']:
    verbose = False

# If --noencrypt, --nosign or --notransfer is specified, put that in config
if arguments['--no-encrypt']:
    config['noencrypt'] = True
else:
    config['noencrypt'] = False

if arguments['--no-sign']:
    config['nosign'] = True
else:
    config['nosign'] = False

if arguments['--no-transfer']:
    config['notransfer'] = True
else:
    config['notransfer'] = False

and so on ...



More information about the Python-list mailing list