2010-11-16 10 views
22

Tengo un argumento opcional que admite una lista de argumentos.Python argparse: ¿Hay alguna manera de especificar un rango en nargs?

quiero decir, debería apoyar:

  • -f 1 2
  • -f 1 2 3

pero no:

  • -f 1
  • -f 1 2 3 4

¿Hay alguna manera de forzar esto dentro de argparse? Ahora estoy usando nargs = "*", y luego comprobando la longitud de la lista.

Editar: Según lo solicitado, lo que necesitaba era poder definir un rango aceptable de argumentos. Es decir, que dice (en el ejemplo) 2 o 3 args es correcto, pero no 1 o 4, o cualquier cosa que no está dentro de la gama 2..3

+0

No entiendo. ¿Quiere decir que quiere poder apoyar, p. entre uno y diez argumentos? – katrielalex

+5

¿Podrían dar más detalles sobre cuáles son las reglas? ¿Desea requerir al menos 2, y como máximo 3 valores? ¿Tienen que ser 1-4 o pueden ser algo? – slf

Respuesta

15

Se puede hacer esto con un custom action:

import argparse 

def required_length(nmin,nmax): 
    class RequiredLength(argparse.Action): 
     def __call__(self, parser, args, values, option_string=None): 
      if not nmin<=len(values)<=nmax: 
       msg='argument "{f}" requires between {nmin} and {nmax} arguments'.format(
        f=self.dest,nmin=nmin,nmax=nmax) 
       raise argparse.ArgumentTypeError(msg) 
      setattr(args, self.dest, values) 
    return RequiredLength 

parser=argparse.ArgumentParser(prog='PROG') 
parser.add_argument('-f', nargs='+', action=required_length(2,3)) 

args=parser.parse_args('-f 1 2 3'.split()) 
print(args.f) 
# ['1', '2', '3'] 

try: 
    args=parser.parse_args('-f 1 2 3 4'.split()) 
    print(args) 
except argparse.ArgumentTypeError as err: 
    print(err) 
# argument "f" requires between 2 and 3 arguments 
+1

Viajero del tiempo aquí. ¡Gran respuesta! Sin embargo, usted está subclasificando 'argparse.Action' aquí ... ¿qué sucede si quiero que mi acción sea' append'? ¿Cómo puedo modificar este código para poder agregar varias instancias de este argumento y también obtener ese efecto de rango especificado? – 2rs2ts

+1

Ah, de hecho, fusionando su código con [esta respuesta] (http://stackoverflow.com/a/5374229/691859) hice lo que estaba buscando. No te preocupes por mí, a menos que pienses lo mismo, en cuyo caso, verifica esa respuesta. – 2rs2ts

+2

Hay un parche propuesto http://bugs.python.org/issue11354 para agregar una opción 'nargs' de rango, p. 'nargs = (2,3)' o 'nargs = '{2,3}'' (notación de estilo 're'). Ese enfoque es más poderoso cuando otros posicionales tienen valores 'nargs' variables. De lo contrario, este enfoque de acción personalizada funciona bien. – hpaulj

Cuestiones relacionadas