2010-11-16 7 views
22

Ho un argomento facoltativo che supporta un elenco di argomenti.Python argparse: esiste un modo per specificare un intervallo in nargs?

Voglio dire, dovrebbe sostenere:

  • -f 1 2
  • -f 1 2 3

ma non:

  • -f 1
  • -f 1 2 3 4

C'è un modo per forzare questo all'interno di argparse? Ora sto usando nargs = "*", e poi controllando la lunghezza dell'elenco.

Modifica: Come richiesto, ciò di cui avevo bisogno è poter definire un intervallo di argomenti accettabili. Voglio dire, dicendo (nell'esempio) 2 o 3 args è giusto, ma non 1 o 4 o qualsiasi cosa che non è all'interno del campo 2..3

+0

Non capisco. Intendi che desideri essere in grado di supportare, ad es. tra uno e dieci argomenti? – katrielalex

+5

Potresti per favore approfondire su quali sono le regole? Vuoi richiedere almeno 2 e al massimo 3 valori? Devono essere 1-4 o possono essere qualcosa? – slf

risposta

15

Si potrebbe fare questo 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

Viaggiatore di tempo qui. Bella risposta! Tuttavia, stai sottoclasse 'argparse.Action' qui ... cosa succede se voglio che la mia azione sia' append'? Come posso modificare questo codice in modo che possa aggiungere più istanze di questo argomento e ottenere anche quell'effetto di intervallo specificato? – 2rs2ts

+1

Ah, in realtà, la fusione del codice con [questa risposta] (http://stackoverflow.com/a/5374229/691859) ha fatto ciò che stavo cercando. Non preoccuparti di me, a meno che tu non stia pensando la stessa cosa, nel qual caso, controlla la risposta. – 2rs2ts

+2

C'è una patch proposta http://bugs.python.org/issue11354 per aggiungere un'opzione 'nargs', ad es. 'nargs = (2,3)' o 'nargs = '{2,3}'' (notazione in stile 're'). Questo approccio è più potente quando altri posizionali hanno valori di 'nargs' variabili. In caso contrario, questo approccio di azione personalizzata funziona correttamente. – hpaulj