Python argparse 互斥组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17909294/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python argparse mutual exclusive group
提问by Sean
What I need is:
我需要的是:
pro [-a xxx | [-b yyy -c zzz]]
I tried this but does not work. Could someone 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")
Thanks!
谢谢!
采纳答案by Jonathan
add_mutually_exclusive_group
doesn't make an entire group mutually exclusive. It makes options within the group mutually exclusive.
add_mutually_exclusive_group
不会使整个群体相互排斥。它使组内的选项相互排斥。
What you're looking for is subcommands. Instead of prog [ -a xxxx | [-b yyy -c zzz]], you'd have:
您正在寻找的是subcommands。而不是 prog [ -a xxxx | [-b yyy -c zzz]],你有:
prog
command 1
-a: ...
command 2
-b: ...
-c: ...
To invoke with the first set of arguments:
使用第一组参数调用:
prog command_1 -a xxxx
To invoke with the second set of arguments:
使用第二组参数调用:
prog command_2 -b yyyy -c zzzz
You can also set the sub command arguments as positional.
您还可以将子命令参数设置为位置。
prog command_1 xxxx
Kind of like git or svn:
有点像 git 或 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')
Test it
测试一下
>>> 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: -b x
Good luck.
祝你好运。
回答by hpaulj
There is a python patch (in development) that would allow you to do this.
http://bugs.python.org/issue10984
有一个 python 补丁(正在开发中)可以让你做到这一点。
http://bugs.python.org/issue10984
The idea is to allow overlapping mutually exclusive groups. So usage
might look like:
这个想法是允许重叠的互斥组。所以usage
可能看起来像:
pro [-a xxx | -b yyy] [-a xxx | -c zzz]
Changing the argparse code so you can create two groups like this was the easy part. Changing the usage
formatting code required writing a custom HelpFormatter
.
更改 argparse 代码以便您可以像这样创建两个组是简单的部分。更改usage
格式代码需要编写自定义HelpFormatter
.
In argparse
, action groups don't affect the parsing. They are just a help
formatting tool. In the help
, mutually exclusive groups only affect the usage
line. When parsing, the parser
uses the mutually exclusive groups to construct a dictionary of potential conflicts (a
can't occur with b
or c
, b
can't occur with a
, etc), and then raises an error if a conflict arises.
在 中argparse
,动作组不影响解析。它们只是一个help
格式化工具。在 中help
,互斥组只影响usage
行。解析时,parser
使用互斥组构造潜在冲突的字典(a
不能与b
或发生c
,b
不能与 发生a
等),然后如果出现冲突则引发错误。
Without that argparse patch, I think your best choice is to test the namespace produced by parse_args
yourself (e.g. if both a
and b
have nondefault values), and raise your own error. You could even use the parser's own error mechanism.
如果没有argparse补丁,我想你最好的选择是测试所产生的命名空间parse_args
自己(例如,如果两者a
并b
具有非默认值),并提高自己的错误。您甚至可以使用解析器自己的错误机制。
parser.error('custom error message')
回答by Oz123
While Jonathan's answeris perfectly fine for complex options, there is a very simple solution which will work for the simple cases, e.g. 1 option excludes 2 other options like in
虽然乔纳森的回答对于复杂的选项非常好,但有一个非常简单的解决方案适用于简单的情况,例如 1 个选项排除 2 个其他选项,例如
command [- a xxx | [ -b yyy | -c zzz ]]
or even as in the original question:
甚至就像在原始问题中一样:
pro [-a xxx | [-b yyy -c zzz]]
Here is how I would 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 options given to a command line wrapper for querying a mongodb. The collection
instance can either call the method aggregate
or the method find
with to optional arguments query
and fields
, hence you see why the first two arguments are compatible and the last one isn't.
我在这里使用命令行包装器的选项来查询 mongodb。该collection
实例可以调用该方法aggregate
或方法find
一起可选参数query
和fields
,因此你看到为什么前两个参数是兼容的,最后一个是没有的。
So now I run parser.parse_args()
and check it's content:
所以现在我运行parser.parse_args()
并检查它的内容:
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 is only working for simple cases and it would become a nightmare to check all the possible options if you have many mutually exclusive options and groups. In that case you should break your options in to command groups like Jonathan suggested.
当然,这个小技巧只适用于简单的情况,如果您有许多互斥的选项和组,检查所有可能的选项将成为一场噩梦。在这种情况下,您应该像 Jonathan 建议的那样将您的选项分成命令组。