Joint exclusive Python group argparse

What I need:

pro [-a xxx | [-b yyy -c zzz]] 

I tried this but did not work. Can anyone help me out?

 group= parser.add_argument_group('Model 2') group_ex = group.add_mutually_exclusive_group() group_ex.add_argument("-a", type=str, action = "store", default = "", help="test") group_ex_2 = group_ex.add_argument_group("option 2") group_ex_2.add_argument("-b", type=str, action = "store", default = "", help="test") group_ex_2.add_argument("-c", type=str, action = "store", default = "", help="test") 

Thank!

+56
python argparse
Jul 28 '13 at 14:37
source share
3 answers

add_mutually_exclusive_group does not make the whole group mutually exclusive. This makes the options within the group mutually exclusive.

What you are looking for is subcommands . Instead of prog [-a xxxx | [-b yyy -c zzz]], you will have:

 prog command 1 -a: ... command 2 -b: ... -c: ... 

To call using the first set of arguments:

 prog command_1 -a xxxx 

To call the second set of arguments:

 prog command_2 -b yyyy -c zzzz 

You can also set auxiliary command arguments as positional.

 prog command_1 xxxx 

A view like git or svn:

 git commit -am git merge develop 

Working example

 # create the top-level parser parser = argparse.ArgumentParser(prog='PROG') parser.add_argument('--foo', action='store_true', help='help for foo arg.') subparsers = parser.add_subparsers(help='help for subcommand') # create the parser for the "command_1" command parser_a = subparsers.add_parser('command_1', help='command_1 help') parser_a.add_argument('a', type=str, help='help for bar, positional') # create the parser for the "command_2" command parser_b = subparsers.add_parser('command_2', help='help for command_2') parser_b.add_argument('-b', type=str, help='help for b') parser_b.add_argument('-c', type=str, action='store', default='', help='test') 

Check him

 >>> parser.print_help() usage: PROG [-h] [--foo] {command_1,command_2} ... positional arguments: {command_1,command_2} help for subcommand command_1 command_1 help command_2 help for command_2 optional arguments: -h, --help show this help message and exit --foo help for foo arg. >>> >>> parser.parse_args(['command_1', 'working']) Namespace(a='working', foo=False) >>> parser.parse_args(['command_1', 'wellness', '-b x']) usage: PROG [-h] [--foo] {command_1,command_2} ... PROG: error: unrecognized arguments: -bx 

Good luck.

+63
Jul 28 '13 at 2:59
source share

While Jonathan's answer is great for complex options, there is a very simple solution that will work for simple cases, for example. 1 excludes 2 other options, such as

 command [- a xxx | [ -b yyy | -c zzz ]] 

or even as in the original question:

 pro [-a xxx | [-b yyy -c zzz]] 

Here's how I do it:

 parser = argparse.ArgumentParser() # group 1 parser.add_argument("-q", "--query", help="query", required=False) parser.add_argument("-f", "--fields", help="field names", required=False) # group 2 parser.add_argument("-a", "--aggregation", help="aggregation", required=False) 

I am using here the options provided by the shell for requesting mongodb. The collection instance can either call the aggregate method or the find method with additional query and fields arguments, so you can see why the first two arguments are compatible and the last is not.

So now I run parser.parse_args() and check its contents:

 args = parser().parse_args() print args.aggregation if args.aggregation and (args.query or args.fields): print "-a and -q|-f are mutually exclusive ..." sys.exit(2) 

Of course, this little hack works only for simple cases, and for nightmares one could check all possible options if you have many mutually exclusive options and groups. In this case, you must break down your options in team groups, as Jonathan suggested.

+21
Dec 28 '14 at 10:38
source share

There is a python patch (in development) that will allow you to do this.
http://bugs.python.org/issue10984

The idea is to allow overlapping mutually exclusive groups. Therefore usage may look like this:

 pro [-a xxx | -b yyy] [-a xxx | -c zzz] 

Changing the argparse code so you can create two groups such as this was the easy part. Changing the usage formatting code requires a custom HelpFormatter .

In argparse , action groups do not affect parsing. This is just a help formatting tool. In help mutually exclusive groups only affect the usage line. In the analysis, parser uses mutually exclusive groups to create a dictionary of potential conflicts ( a cannot occur with b or c , b cannot happen with a , etc.). And then causes an error if a conflict occurs.

Without this argparse patch, I believe your best bet is to check the namespace created by parse_args yourself (for example, if both a and b have insecure values) and raise your own error. You can even use your own parser analysis engine.

 parser.error('custom error message') 
+4
Jul 30 '13 at 7:19
source share



All Articles