在Python argparse中使用字典

4 投票
3 回答
5541 浏览
提问于 2025-04-17 23:49

我有一个字典,这个字典把人类能理解的值映射到三个不同的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")。而且因为我多次使用这个,所以每次都得这么做。

3 个回答

1

在编程中,有时候我们需要处理一些数据,比如从一个地方获取数据,然后在程序中使用这些数据。这个过程可能会涉及到很多步骤,比如连接到数据库、查询数据、处理数据等等。

在这个过程中,可能会遇到一些问题,比如数据格式不对、连接失败等等。这些问题可能会导致程序出错,或者获取不到我们想要的数据。

为了避免这些问题,我们可以采取一些措施,比如检查数据的格式、确保连接正常、使用错误处理机制等等。这样可以提高程序的稳定性和可靠性。

总之,处理数据是编程中一个重要的部分,我们需要认真对待,确保每一步都能顺利进行。

values = { "on": True, "off": False, "switch": None }
parser.add_argument("-v", "--value", choices=values.keys())
value = values.get(args.value)
2

我无法对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)
4

最简单的改动是使用

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)

这种“类型”方法会破坏上面提到的choices的使用,因为choices是在转换之后应用的。为了保留你使用choices的方式,可以这样做:

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'不在choices中,所以你会得到预期的错误信息。

使用“action”并结合从argparse.Action派生的类,而不是使用type,应该能更聪明地解决这个问题,具体可以参考文档

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)

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

撰写回答