argparse(python)是否支持互斥的参数组?

aet*_*ter 21 python argparse

如果我有参数'-a', '-b', '-c', '-d',使用该add_mutually_exclusive_group()函数我的程序将只使用其中一个.有没有办法将它结合起来,以便程序只接受'-a 999 -b 999''-c 999 -d 999'

编辑:添加一个简单的程序,以便更清晰:

>>> parser = argparse.ArgumentParser()
>>> group = parser.add_mutually_exclusive_group()
>>> group.add_argument('-a')
>>> group.add_argument('-b')
>>> group.add_argument('-c')
>>> group.add_argument('-d')
Run Code Online (Sandbox Code Playgroud)

然后./app.py -a | ./app.py -b | ./app.py -c | ./app.py -d才能被召唤.是否有可能让argparse组成为排除组,因此只能./app.py -a .. -b .. | ./app.py -c .. -d ..被调用?

got*_*nes 6

编辑:没关系.因为argparse在调用时必须创建一个选项是可怕的选择group.add_argument.那不是我的设计选择.如果您迫切需要此功能,可以尝试使用ConflictsOptionParser:

# exclusivegroups.py
import conflictsparse

parser = conflictsparse.ConflictsOptionParser()
a_opt = parser.add_option('-a')
b_opt = parser.add_option('-b')
c_opt = parser.add_option('-c')
d_opt = parser.add_option('-d')

import itertools
compatible_opts1 = (a_opt, b_opt)
compatible_opts2 = (c_opt, d_opt)
exclusives = itertools.product(compatible_opts1, compatible_opts2)
for exclusive_grp in exclusives:
    parser.register_conflict(exclusive_grp)


opts, args = parser.parse_args()
print "opts: ", opts
print "args: ", args
Run Code Online (Sandbox Code Playgroud)

因此,当我们调用它时,我们可以看到我们获得了预期的效果.

$ python exclusivegroups.py -a 1 -b 2
opts:  {'a': '1', 'c': None, 'b': '2', 'd': None}
args:  []
$ python exclusivegroups.py -c 3 -d 2
opts:  {'a': None, 'c': '3', 'b': None, 'd': '2'}
args:  []
$ python exclusivegroups.py -a 1 -b 2 -c 3
Usage: exclusivegroups.py [options]

exclusivegroups.py: error: -b, -c are incompatible options.
Run Code Online (Sandbox Code Playgroud)

警告消息不告诉你,这两个'-a''-b'是不兼容的'-c',但是一个更合适的错误信息,可以制作.下面的老,错误的答案.

OLDER EDIT: [这个编辑错了,虽然如果这样工作不会只是一个完美的世界argparse吗?]我之前的回答实际上是不正确的,你应该能够argparse通过为每个互斥选项指定一个组来做到这一点.我们甚至可以itertools用来概括这个过程.并且这样做我们不必明确地输入所有组合:

import itertools
compatible_opts1 = ('-a', '-b')
compatible_opts2 = ('-c', '-d')
exclusives = itertools.product(compatible_opts1, compatible_opts2)
for exclusive_grp in exclusives:
    group = parser.add_mutually_exclusive_group()
    group.add_argument(exclusive_grp[0])
    group.add_argument(exclusive_grp[1])
Run Code Online (Sandbox Code Playgroud)


unh*_*mer 5

我自己偶然发现了这个问题.从我对argparse文档的阅读中,似乎没有一种简单的方法可以在argparse中实现这一点.我考虑过使用parse_known_args,但这很快就算写了argparse的特殊用途版本;-)

也许错误报告是有序的.同时,如果你愿意让你的用户做一些额外的打字,你可以用子组伪造它(比如git和svn的参数如何工作),例如

    subparsers = parser.add_subparsers()
    p_ab = subparsers.add_parser('ab')
    p_ab.add_argument(...)

    p_cd = subparsers.add_parser('cd')
    p_cd.add_argument(...)
Run Code Online (Sandbox Code Playgroud)

不理想,但至少它给了你argparse的好处而没有太多丑陋的hackery.我最终取消了交换机,只使用了具有所需子参数的subparser操作.