4

I have a script with two primary functions, upgrade and provision. I'm using subparsers as a way to dictate the action being performed by the script but I want to avoid them being used together.

This is a snippet of the code:

import argparse def main(): parser = argparse.ArgumentParser() subparser = parser.add_subparsers(help='sub-command help') parser.add_argument('--user', '-u', help='User', default=None, required=True) parser.add_argument('--password', '-p', help='Password', default=None, required=True) parser.add_argument('--server', '-s', help='server with Admin functionality', default=None, required=True) subparser_prov = subparser.add_parser('provision', help='Provision new managers') subparser_prov.set_defaults(which='provision') subparser_upgr = subparser.add_parser('upgrade', help='Upgrade worker by replacing them') subparser_upgr.set_defaults(which='upgrade') subparser_upgr.add_argument('--version', help='Deployment version', default=None) args = vars(parser.parse_args()) print args['user'] print args['password'] if args['which'] == 'provision': print 'Provisioning new environment!' elif args['which'] == 'upgrade': print 'Upgrading workers! %s' % args['version'] if __name__ == "__main__": main() 

I know that add_mutually_exclusive_group() is supported by both parser and subparser however this is specifically for arguments. With a subparser is there any method for avoiding them being used together?

2 Answers 2

7

Yes, they are mutually exclusive, though the mechanism is different from the MXGroups.

subparser = parser.add_subparsers(help='sub-command help') 

is an add_argument command that creates a positional argument, with a special action class. Among other things it has a choices value.

subparser.add_parser(...) 

creates a parser, and adds its 'name' (and aliases) to subparser's choices.

A positional argument is parsed only once, so only one subparser will be handled. And the subparser usually processes all of the remaining arguments.

There have been SO questions that ask about getting around that - that is they want to handle multiple subparsers. The way to do that is tricky, and involves calling a parser recursively (or repeatedly), each time with a smaller set of the original arguments.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the confirmation, this makes perfect sense.
@hpaulj You said to workaround to have multiple subparsers invoked from single command. Can you elaborate on how to do this? Or point me to any earlier questions.
0

As far as I can tell subparsers are mutually exclusive by default:

Note that the object returned by parse_args() will only contain attributes for the main parser and the subparser that was selected by the command line (and not any other subparsers). So in the example above, when the a command is specified, only the foo and bar attributes are present, and when the b command is specified, only the foo and baz attributes are present.

From the python documentation on subparsers.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.