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()