Python Argparse共有独家组

发布于 2025-02-01 12:24:30 字数 533 浏览 2 评论 0原文

我需要的是:

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

我尝试过,但行不通。有人可以帮我吗?

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

谢谢!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

耳钉梦 2025-02-08 12:24:30

add_mutaly_exclusive_group不会使整个组相互排斥。它在组中互斥的选项。

您正在寻找的是 sub-commands 。而不是prog [-a xxxx | [-b yyy -c zzz]],您必须:

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

使用第一组参数调用:

prog command_1 -a xxxx

使用第二组参数调用:

prog command_2 -b yyyy -c zzzz

您还可以将sub命令参数设置为位置。

prog command_1 xxxx

有点像git或svn:

git commit -am
git merge develop

工作示例

# 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', dest="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')

测试它

>>> 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(subcommand='command_1', 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

好运。

add_mutually_exclusive_group doesn't make an entire group mutually exclusive. It makes options within the group mutually exclusive.

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

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 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', dest="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(subcommand='command_1', 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.

疾风者 2025-02-08 12:24:30

Jonathan的答案对于复杂的选项来说是完全可以的,有一个非常简单的解决方案,它将适用于简单的情况,例如1选项不包括2个其他选项,例如在

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

原始问题中或什至是原始问题:

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

这是我的操作方式:

parser = argparse.ArgumentParser()

# group 1 
parser.add_argument("-q", "--query", help="query")
parser.add_argument("-f", "--fields", help="field names")

# group 2 
parser.add_argument("-a", "--aggregation", help="aggregation")

我在此处使用命令行包装器的选项来查询mongoDB。 集合实例可以调用方法汇总或方法查找 with to to to to to to to to to to to to to to to to to to to to to to to to to to QUERY> QUERY>查询和>字段,因此您会明白为什么前两个参数兼容而最后一个参数不兼容。

因此,现在我运行parser.parse_args()并检查其内容:

args = parser.parse_args()

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

当然,这个小骇客仅适用于简单的情况,如果您有许多相互的相互互动,请检查所有可能的选项,将成为一场噩梦独家选项和组。在这种情况下,您应该像乔纳森(Jonathan)所建议的那样将选项分解为命令组。

While Jonathan's answer is 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

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")
parser.add_argument("-f", "--fields", help="field names")

# group 2 
parser.add_argument("-a", "--aggregation", help="aggregation")

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.

So now I run parser.parse_args() and check it's content:

args = parser.parse_args()

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.

晨与橙与城 2025-02-08 12:24:30

如果您不想要地下书,目前可以通过相互排他性的组来完成,但是公平的警告,它涉及访问私人变量,因此请自行使用它。这个想法是您希望-a-b-c相互排斥,但是-b-c不想彼此相互排斥,

import argparse
p = argparse.ArgumentParser()

# first set up a mutually exclusive group for a and b
g1 = p.add_mutually_exclusive_group()
arg_a = g1.add_argument('-a')  # save this _StoreAction for later
g1.add_argument('-b')

# now set up a second group for a and c 
g2 = p.add_mutually_exclusive_group()
g2.add_argument('-c')
g2._group_actions.append(arg_a)  # this is the magic/hack

现在我们有-a -c独有-b

a = p.parse_args(['-a', '1'])
# a.a = 1, a.b = None, a.c = None

a = p.parse_args(['-a', '1', '-b', '2'])
# usage: prog.py [-h] [-a A | -b B] [-c C]
# prog.py: error: argument -b: not allowed with argument -a

请注意,它确实弄乱了帮助消息,但是您可能可以覆盖它,或者只是因为您拥有想要的功能而忽略它,这可能还是更重要的。

如果要确保我们是否使用B和C的任何一个,我们必须使用它们,然后在实例化相互排斥的组时,只需添加quired offer = true关键字arg即可。

If you don't want subparsers, this can currently be done with mutually exclusive groups, but fair warning, it involves accessing private variables so use it at your own risk. The idea is you want -a to be mutually exclusive with -b and -c, but -b and -c don't want to be mutually exclusive with each other

import argparse
p = argparse.ArgumentParser()

# first set up a mutually exclusive group for a and b
g1 = p.add_mutually_exclusive_group()
arg_a = g1.add_argument('-a')  # save this _StoreAction for later
g1.add_argument('-b')

# now set up a second group for a and c 
g2 = p.add_mutually_exclusive_group()
g2.add_argument('-c')
g2._group_actions.append(arg_a)  # this is the magic/hack

Now we've got -a exclusive to both -c and -b.

a = p.parse_args(['-a', '1'])
# a.a = 1, a.b = None, a.c = None

a = p.parse_args(['-a', '1', '-b', '2'])
# usage: prog.py [-h] [-a A | -b B] [-c C]
# prog.py: error: argument -b: not allowed with argument -a

Note, it does mess up the help message, but you could probably override that, or just ignore it because you've got the functionality you want, which is probably more important anyway.

If you want to ensure if we're using any of b and c, we have to use both of them, then simply add the required=True keyword arg when instantiating the mutually exclusive groups.

入怼 2025-02-08 12:24:30

有一个Python补丁(在开发中)可以让您这样做。
http://bugs.python.org/issue10984

这个想法是允许重叠的互斥组重叠。因此,用法可能看起来像:

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

更改ArgParse代码,因此您可以创建两个类似的组是简单的部分。更改用法格式化代码所需的编写自定义helpformatter

argparse中,行动组不会影响解析。它们只是帮助格式化工具。在帮助中,相互排斥的组仅影响使用行。解析时,解析器使用互斥组来构建潜在冲突的字典(a不能使用b发生。 cba等)中无法发生,然后如果发生冲突,则会引起错误。

没有该ArgParse补丁,我认为您的最佳选择是测试由parse_args您自己产生的名称空间(例如,如果a a 和b均具有非eftefault值),并提出自己的错误。您甚至可以使用解析器自己的错误机制。

parser.error('custom error message')

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

The idea is to allow overlapping mutually exclusive groups. So usage might look like:

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.

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.

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.

parser.error('custom error message')
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文