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

时间:2011-01-22 21:05:14

标签: 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')

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

4 个答案:

答案 0 :(得分: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

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

$ 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'不兼容,但可以制作更合适的错误消息。下面更老,错误的答案。

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

答案 1 :(得分: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(...)

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

答案 2 :(得分:0)

次级评判者?

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

答案 3 :(得分:0)

@hpaulj的注释中引用的con_to_index = dict() index_to_con = dict() var_to_index = pyo.ComponentMap() index_to-var = dict() for ndx, var in enumerate(nlp.get_pyomo_variables()): var_to_index[var] = ndx index_to_var[ndx] = var for ndx, con in enumerate(nlp.get_pyomo_constraints()): con_to_index[con] = ndx index_to_con[ndx] = con 增强请求在九年多之后仍然没有解决,因此我认为其他人可能会从我刚刚发现的变通方法中受益。基于增强请求中的this comment,我发现我可以使用以下语法向两个不同的互斥组添加一个选项:

db.collection("entidades").addSnapshotListener { (querySnapshot, error) in
    guard let querySnapshot = querySnapshot else { return }
    self.entidades = querySnapshot.documents.compactMap { document -> Entidad? in 
        try? document.data(as: Entidad.self)
    }
}

这对我来说足够好了

argparse

访问#!/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在无法使用时可以一起使用(!)。但是,我正在使用此脚本进行测试,所以我不太担心。 (我认为修正“真实”使用消息将需要比我更多的时间来完成这项任务,但是如果您知道如何使用此技巧,请发表评论。)