Use dictionary for Python argparse

风流意气都作罢 提交于 2019-12-01 18:47:02

问题


I have a dictionary which maps human readable values to three different Python specific values. How can the argparse Python module use this dictionary to get me the specific values while the user can choice between the keys.

Currently I have this:

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

The problem is, that argparse doesn't return True, False or None if the parameter is given. Is there an easy way to add this feature? Of course I would be able to execute something like this afterwards:

args.value = values[args.value]

This is actually what I'm doing currently, but this doesn't work well with the default value (I would have to check if the value is already None or set the default to "switch"). And as I'm using this multiple times I would have to do that every time.


回答1:


The smallest change would be to use

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

so you would get None for any entry not in the dict (eg default).

Another option is to misuse the type keyword of argparse:

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

The "type" approach breaks the use of choices as used above, since choices is applied after the conversion. One possibility to preserve your use of choices would be:

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

In this case convertvalues returns the right values if 'on','off','switch' and None are used and returns the given values if something else was given (eg. 'bla'). Since 'bla' is not in choices, you get the expected error message.

Using "action" with a class derived from argparse.Action instead of type should do the job the smart way, as given in the 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)

Of course this is not perfect, a better solution would overwrite the Acion init to get the dictionary and leave out the hardcoded value_dict.




回答2:


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



回答3:


I couldn't comment on oekopez' answer, but this change would be make the class available to be used for any dictionary passed to the add_argument action.

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)


来源:https://stackoverflow.com/questions/22635675/use-dictionary-for-python-argparse

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!