Use el diccionario para Python argparse

Tengo un diccionario que asigna valores humanos legibles a tres valores específicos de Python diferentes. ¿Cómo puede el módulo Python argparse usar este diccionario para obtener los valores específicos mientras que el usuario puede elegir entre las teclas?

Actualmente tengo esto:

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']) : on >>> parse(['-v', 'off']) : off >>> parse(['-v', 'switch']) : switch >>> parse([]) : None 

El problema es que argparse no devuelve True , False o None si se proporciona el parámetro. ¿Hay una manera fácil de agregar esta característica? Por supuesto que sería capaz de ejecutar algo como esto después:

 args.value = values[args.value] 

Esto es realmente lo que estoy haciendo actualmente, pero esto no funciona bien con el valor predeterminado (tendría que verificar si el valor ya es Ninguno o establecer el valor predeterminado en "switch" ). Y como lo estoy usando varias veces, tendría que hacerlo cada vez.

El cambio más pequeño sería usar

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

así que obtendría Ninguno para cualquier entrada que no esté en el dict (por ejemplo, por defecto).

Otra opción es hacer un mal uso de la palabra clave de tipo argparse:

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

El enfoque de “tipo” rompe el uso de opciones como se usó anteriormente, ya que las opciones se aplican después de la conversión. Una posibilidad para preservar su uso de opciones sería:

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

En este caso, convertvalues ​​devuelve los valores correctos si se usan ‘on’, ‘off’, ‘switch’ y None y devuelve los valores dados si se dio algo más (por ejemplo, ‘bla’). Como ‘bla’ no está en las opciones, aparece el mensaje de error esperado.

El uso de “acción” con una clase derivada de argparse.Action en lugar de tipo debe hacer el trabajo de manera inteligente, como se indica en los documentos :

 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) 

Por supuesto, esto no es perfecto, una mejor solución sobrescribiría el inicio de Acion para obtener el diccionario y dejar de lado el valor_dicto codificado.

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

No pude comentar sobre la respuesta de oekopez, pero este cambio hará que la clase esté disponible para cualquier diccionario pasado a la acción 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)