gem/git-style command line arguments in Python gem/git-style command line arguments in Python python python

gem/git-style command line arguments in Python


Yes, argparse with add_subparsers().

It's all well explained in the Sub-commands section.

Copying one of the examples from there:

>>> parser = argparse.ArgumentParser()>>> subparsers = parser.add_subparsers()>>> checkout = subparsers.add_parser('checkout', aliases=['co'])>>> checkout.add_argument('foo')>>> parser.parse_args(['checkout', 'bar'])Namespace(foo='bar')

Edit: Unfortunately there's no self generated special help command, but you can get the verbose help message (that you seem to want) with -h or --help like one normally would after the command:

$ ./MyApp.py branch --help

By verbose I don't mean that is like a man page, it's like every other --help kind of help: listing all the arguments, etc...

Example:

>>> parser = argparse.ArgumentParser()>>> subparsers = parser.add_subparsers(description='Sub description')>>> checkout = subparsers.add_parser('checkout', description='Checkout description')>>> checkout.add_argument('foo', help='This is the foo help')>>> parser.parse_args(['checkout', '--help'])usage:  checkout [-h] fooCheckout descriptionpositional arguments:  foo         This is the foo helpoptional arguments:  -h, --help  show this help message and exit

If you need to, it should be easy to implement an help command that redirects to --help.


A reasonable hack to get the gem/git style "help" behavior (I just wrote this for what I'm working on anyway):

parser = argparse.ArgumentParser()subparsers = parser.add_subparsers(dest='sub_commands')parser_branch = subparsers.add_parser('branch', description='list of branches')parser_help = subparsers.add_parser('help')parser_help.add_argument('command', nargs="?", default=None)# I can't find a legitimate way to set a default subparser in the docs#   If you know of one, please let me know!if len(sys.argv) < 2:    sys.argv.append('--help')parsed = parser.parse_args()if parsed.sub_commands == "help":    if not parsed.command:        parser.parse_args(['--help'])    else:        parser.parse_args([parsed.command, '--help'])

argparse is definitely a step up from optparse and other python solutions I've come across. But IMO the gem/git style of handling args is just a more logical and safer way to do things so it's annoying that it's not supported.


I wanted to do something similar to git commands, where I would load a second script based off of one of the command line options, and have that script populate more command line options, and also have the help work.

I was able to do this by disabling the help option, parse known args, add more arguments, re-enable the help option, and then parse the rest of the arguments.

This is what I came up with.

import argparse #Note add_help=Falsearg_parser = argparse.ArgumentParser(description='Add more arguments after parsing.',add_help=False)arg_parser.add_argument('MODE',  default='default',type=str, help='What commands to use')args = arg_parser.parse_known_args()[0]if args.MODE == 'branch':   arg_parser.add_argument('-d', '--delete', default='Delete a branch')   arg_parser.add_argument('-m', '--move', default='move a branch')elif args.MODE == 'clone' :   arg_parser.add_argument('--local', '-l')   arg_parser.add_argument('--shared')#Finally re-enable the help option, and reparse the argumentsarg_parser.add_argument(            '-h', '--help',            action='help', default=argparse.SUPPRESS,            help=argparse._('show this help message and exit'))args = arg_parser.parse_args()