使用 Python argparse 的字典

Posted

技术标签:

【中文标题】使用 Python argparse 的字典【英文标题】:Use dictionary for 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'有问题吗?预先指定默认选项是一种很好的做法。 【参考方案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)

【讨论】:

以上是关于使用 Python argparse 的字典的主要内容,如果未能解决你的问题,请参考以下文章

编程54--python学习28Namespace与dict的相互转换,保存Namespace,以字典形式传入argparse的参数

Python+argparse+notebook

使用其他命名空间/字典更新 argparse 命名空间

使用 Python argparse 的字典

使用 argparse 和 python 接受字典作为参数 [重复]

将 Python argparse.Namespace() 视为字典的正确方法是啥?