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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 09:27:16  来源:igfitidea点击:

Python argparse mutual exclusive group

pythonargparse

提问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_groupdoesn'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 usagemight 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 usageformatting code required writing a custom HelpFormatter.

更改 argparse 代码以便您可以像这样创建两个组是简单的部分。更改usage格式代码需要编写自定义HelpFormatter.

In argparse, action groups don't affect the parsing. They are just a helpformatting tool. In the help, mutually exclusive groups only affect the usageline. When parsing, the parseruses the mutually exclusive groups to construct a dictionary of potential conflicts (acan't occur with bor c, bcan't occur with a, etc), and then raises an error if a conflict arises.

在 中argparse,动作组不影响解析。它们只是一个help格式化工具。在 中help,互斥组只影响usage行。解析时,parser使用互斥组构造潜在冲突的字典(a不能与b或发生cb不能与 发生a等),然后如果出现冲突则引发错误。

Without that argparse patch, I think your best choice is to test the namespace produced by parse_argsyourself (e.g. if both aand bhave nondefault values), and raise your own error. You could even use the parser's own error mechanism.

如果没有argparse补丁,我想你最好的选择是测试所产生的命名空间parse_args自己(例如,如果两者ab具有非默认值),并提高自己的错误。您甚至可以使用解析器自己的错误机制。

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 collectioninstance can either call the method aggregateor the method findwith to optional arguments queryand fields, hence you see why the first two arguments are compatible and the last one isn't.

我在这里使用命令行包装器的选项来查询 mongodb。该collection实例可以调用该方法aggregate或方法find一起可选参数queryfields,因此你看到为什么前两个参数是兼容的,最后一个是没有的。

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 建议的那样将您的选项分成命令组。