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

2024-04-29 18:41:45 发布

您现在位置:Python中文网/ 问答频道 /正文

如果我有参数'-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')

然后只能调用./app.py -a | ./app.py -b | ./app.py -c | ./app.py -d。是否可以让argparse组作为排除组,以便只调用./app.py -a .. -b .. | ./app.py -c .. -d ..


Tags: 方法函数py程序addappparser编辑
3条回答

次犯罪者?

类似于unhammer的答案,但是有更多的用户控制。注意:我还没有实际测试过这个方法,但是它应该在理论上和python的功能上都能工作。

您可以创建两个解析器,两个组各一个,并使用条件语句来完成互斥部分。基本上只对参数解析的一部分使用argparse。使用这种方法,您也可以超越unhammer的答案的限制。

# Python 3
import argparse

try:
    parser = argparse.ArgumentParser()
    parser.add_argument('-a')
    parser.add_argument('-b')
    args = parser.parse_args
except argparse.ArgumentError:
    parser = argparse.ArgumentParser()
    parser.add_argument('-c')
    parser.add_argument('-d')
    args = parser.parse_args

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

也许有个错误报告。同时,如果你愿意让你的用户做一些额外的输入,你可以用子组(比如g it和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(...)

不太理想,但至少它给了你从argparse没有太多丑陋的黑客好。我最终放弃了开关,只使用了子库操作和所需的子库。

编辑:没关系。因为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

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

$ 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.

警告消息不会通知您'-a''-b'都与'-c'不兼容,但是可以创建更合适的错误消息。下面是更老的错误答案。

旧的编辑:[这个编辑是错误的,尽管如果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])

相关问题 更多 >