如果我有参数'-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 ..
?
发布于 2011-01-23 05:31:45
编辑:不要紧。因为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])
发布于 2012-11-20 23:05:00
我自己也偶然发现了这个问题。从我对argparse文档的阅读来看,似乎没有一种简单的方法可以在argparse中实现这一点。我考虑过使用parse_known_args,但这很快就相当于编写了一个特殊用途的argparse版本;-)
也许bug报告是合适的。同时,如果你愿意让你的用户做一点额外的输入,你可以用子组来伪造它(比如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(...)
不是很理想,但至少它给你带来了argparse带来的好处,没有太多丑陋的破解。我最终去掉了开关,只使用子解析器操作和所需的子参数。
发布于 2020-04-01 03:08:58
在@hpaulj的评论中提到的argparse
增强请求在九年多之后仍然是开放的,所以我想其他人可能会从我刚刚发现的解决办法中受益。基于增强请求中的this comment,我发现可以使用以下语法将选项添加到两个不同的互斥组中:
#!/usr/bin/env python
import argparse
import os
import sys
def parse_args():
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
parser.add_argument("-d", "--device", help="Path to UART device", default="./ttyS0")
mutex_group1 = parser.add_mutually_exclusive_group()
mutex_group2 = parser.add_mutually_exclusive_group()
mutex_group1.add_argument(
"-o",
"--output-file",
help="Name of output CSV file",
default="sensor_data_sent.csv",
)
input_file_action = mutex_group1.add_argument(
"-i", "--input-file", type=argparse.FileType("r"), help="Name of input CSV file"
)
# See: https://bugs.python.org/issue10984#msg219660
mutex_group2._group_actions.append(input_file_action)
mutex_group2.add_argument(
"-t",
"--time",
type=int,
help="How long to run, in seconds (-1 = loop forever)",
default=-1,
)
# Add missing ']' to usage message
usage = parser.format_usage()
usage = usage.replace('usage: ', '')
usage = usage.replace(']\n', ']]\n')
parser.usage = usage
return parser.parse_args()
if __name__ == "__main__":
args = parse_args()
print("Args parsed successfully...")
sys.exit(0)
这对我的目的来说已经足够好用了:
$ ./fake_sensor.py -i input.csv -o output.csv
usage: fake_sensor.py [-h] [-d DEVICE] [-o OUTPUT_FILE | [-i INPUT_FILE | -t TIME]]
fake_sensor.py: error: argument -o/--output-file: not allowed with argument -i/--input-file
$ ./fake_sensor.py -i input.csv -t 30
usage: fake_sensor.py [-h] [-d DEVICE] [-o OUTPUT_FILE | [-i INPUT_FILE | -t TIME]]
fake_sensor.py: error: argument -t/--time: not allowed with argument -i/--input-file
$ ./fake_sensor.py -i input.csv
Args parsed successfully...
$ ./fake_sensor.py -o output.csv
Args parsed successfully...
$ ./fake_sensor.py -o output.csv -t 30
Args parsed successfully...
当然,访问argparse
的私有成员相当脆弱,所以我可能不会在生产代码中使用这种方法。此外,精明的读者可能会注意到用法消息具有误导性,因为它意味着-o
和-i
可以一起使用,而它们不能(!)但是,我使用这个脚本只是为了测试,所以我并不太担心。(我认为,“真正地”修复使用消息需要的时间比我为这项任务腾出的时间要多得多,但如果你知道一个聪明的技巧,请发表评论。)
https://stackoverflow.com/questions/4770576
复制相似问题