【问题标题】:Use dictionary for Python argparse使用 Python argparse 的字典
【发布时间】:2014-05-03 08:39:10
【问题描述】:

我有一个字典,它将人类可读的值映射到三个不同的 Python 特定值。 argparse Python 模块如何在用户可以在键之间进行选择的同时使用此字典来获取特定值。

目前我有这个:

def parse(a):
    values = { "on": True, "off": False, "switch": None }
    parser = argparse.ArgumentParser()
    parser.add_argument("-v", "--value", choices=values, default=None)
    args = parser.parse_args(a)
    print("{}: {}".format(type(args.value), args.value))

>>> parse(['-v', 'on'])
<type 'str'>: on
>>> parse(['-v', 'off'])
<type 'str'>: off
>>> parse(['-v', 'switch'])
<type 'str'>: switch
>>> parse([])
<type 'NoneType'>: None

问题是,如果给定参数,argparse 不会返回TrueFalseNone。有没有简单的方法来添加这个功能?当然,之后我可以执行这样的操作:

args.value = values[args.value]

这实际上是我目前正在做的事情,但这不适用于默认值(我必须检查该值是否已经为 None 或将默认值设置为 "switch")。而且由于我多次使用它,所以我每次都必须这样做。

【问题讨论】:

  • 指定type=values.__getitem__ 就可以了。不过,不知道这是否是一个好的解决方案;我现在睡眠不足,所以我不知道我是否有好的想法。
  • 设置`default='switch'有问题吗?预先指定默认选项是一种很好的做法。

标签: python dictionary argparse


【解决方案1】:

最小的变化是使用

args.value = values.get(args.values)

所以你会得到 None 对于任何不在字典中的条目(例如默认)。

另一种选择是滥用 argparse 的 type 关键字:

values = { "on": True, "off": False, "switch": None }
def convertvalues(value):
    return values.get(value)
parser.add_argument('-v','--value',type=convertvalues)

“类型”方法打破了上面使用的选择,因为选择是在转换之后应用的。保留您对选择的使用的一种可能性是:

def convertvalues(value):
     return values.get(value,value)
parser.add_argument('-v','--value',type=convertvalues,
                                   choices=[True,False,None],
                                   default=None)

在这种情况下,如果使用 'on'、'off'、'switch' 和 None,convertvalues 会返回正确的值,如果给出了其他值(例如,'bla'),则返回给定的值。由于 'bla' 不在选项中,因此您会收到预期的错误消息。

将“action”与派生自 argparse.Action 的类一起使用而不是 type 应该以聪明的方式完成这项工作,如 docs 中所述:

class DictAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        value_dict = { "on": True, "off": False, "switch": None }
        setattr(namespace, self.dest, value_dict.get(values))
parser.add_argument('-v','--value',action=DictAction,
                                   choices=['on','off','switch'],
                                   default=None)

当然这并不完美,更好的解决方案是覆盖 Acion init 以获取字典并省略硬编码的 value_dict。

【讨论】:

  • 我猜type参数应该设置为convertvalues?
  • 好的,当我使用 type 时,它会在 parseargs 中告诉我:“argument -v/--value: invalid selection: False(从 'on'、'switch'、'off' 中选择)”
  • 当然,它需要是转换值,抱歉错字。对于您的第二个 cmets,我相信您留下了选择。Choices 在转换后进行比较,因此您需要执行choices=values.values()。但是,由于您从 get 获取任何输入的 None,因此这种方法会破坏选择。我会稍微更新一下答案以供选择。
  • 但这会影响选项在帮助文本中的显示方式。目前是usage: [-h] [-v {on,switch,off}]。看来我必须在之后手动翻译该值:(
  • 虽然这种自定义 Action 方法很好,但它最终所做的只是在不同的时间和地点应用 get
【解决方案2】:
values = { "on": True, "off": False, "switch": None }
parser.add_argument("-v", "--value", choices=values.keys())
value = values.get(args.value)

【讨论】:

  • argparse 自动检查字典键。
【解决方案3】:

我无法评论 oekopez 的回答, 但此更改将使该类可用于传递给 add_argument 操作的任何字典。

class DictAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        setattr(namespace, self.dest, self.choices.get(values, self.default))

value_dict = { "on": True, "off": False, "switch": None }
parser.add_argument('-v','--value',action=DictAction,
                               choices=value_dict,
                               default=None)

【讨论】:

    猜你喜欢
    • 2015-07-11
    • 2018-01-04
    • 2021-09-24
    • 2020-08-08
    • 1970-01-01
    • 2019-07-06
    • 2013-06-06
    • 2011-05-13
    相关资源
    最近更新 更多