2012-02-22 19 views
57

Estoy tratando de pasar una lista de argumentos a una secuencia de comandos python utilizando la biblioteca argh. Algo que puede tomar entradas como estas:python argh/argparse: ¿Cómo puedo pasar una lista como un argumento de línea de comandos?

./my_script.py my-func --argA blah --argB 1 2 3 4 
./my_script.py my-func --argA blah --argB 1 
./my_script.py my-func --argA blah --argB 

Mi código interno se ve así:

import argh 

@argh.arg('--argA', default="bleh", help='My first arg') 
@argh.arg('--argB', default=[], help='A list-type arg--except it\'s not!') 
def my_func(args): 
    "A function that does something" 

    print args.argA 
    print args.argB 

    for b in args.argB: 
     print int(b)*int(b) #Print the square of each number in the list 
    print sum([int(b) for b in args.argB]) #Print the sum of the list 

p = argh.ArghParser() 
p.add_commands([my_func]) 
p.dispatch() 

Y aquí es cómo se comporta:

$ python temp.py my-func --argA blooh --argB 1 
blooh 
['1'] 
1 
1 

$ python temp.py my-func --argA blooh --argB 10 
blooh 
['1', '0'] 
1 
0 
1 

$ python temp.py my-func --argA blooh --argB 1 2 3 
usage: temp.py [-h] {my-func} ... 
temp.py: error: unrecognized arguments: 2 3 

El problema parece bastante sencillo: argh es solo acepta el primer argumento y lo trata como una cadena. ¿Cómo puedo hacer que "espere" una lista de enteros en su lugar?

Veo how this is done in optparse, pero ¿qué pasa con (no desaprobado) argparse? ¿O usando la sintaxis decorada mucho más bonita de argh? Estos parecen mucho más pitonicos.

Respuesta

76

Con argparse, sólo tiene que utilizar type=int

import argparse 

parser = argparse.ArgumentParser() 
parser.add_argument('-a', '--arg', nargs='+', type=int) 
print parser.parse_args() 

Ejemplo de salida:

$ python test.py -a 1 2 3 
Namespace(arg=[1, 2, 3]) 

Editar: No estoy familiarizado con argh, pero parece ser sólo una envoltura alrededor de argparse y esto funcionó para mí:

import argh 

@argh.arg('-a', '--arg', nargs='+', type=int) 
def main(args): 
    print args 

parser = argh.ArghParser() 
parser.add_commands([main]) 
parser.dispatch() 

Ejemplo de salida:

$ python test.py main -a 1 2 3 
Namespace(arg=[1, 2, 3], function=<function main at 0x.......>) 
+1

Awesome! Modifiqué el código para incluir la línea: @ argh.arg ('- argB', por defecto = [], help = 'Una lista-tipo arg - excepto' \ 's no!', Nargs = '+', type = int) y argh le gustó. ¡Gracias por la ayuda! – Abe

+0

Sí, esta es la forma correcta. Las versiones recientes de Argh también admiten la notación "natural", más pitonica: 'func (argA, * argB)' (aunque '* args' maps a' nargs = '*' 'en vez de' nargs = '+' ') . –

+0

@jcollado: veo que cuando uso nargs =, no puedo hacer -a = 1 2 3. Lo que quiero decir es que use '=' después del argumento metavar. Cualquier solución que me permita usar = para cada arg. Por ejemplo, en tu ejemplo quiero hacerlo, python test.py main -a = 1 2 3 –

1

I para tener acceso a cada valor de parámetro, el código siguiente puede ser útil.

import argparse 
parser = argparse.ArgumentParser() 
parser.add_argument('-a', '--arg', nargs='+', type=int) 
args = vars(parser.parse_args()) 

print "first parameter:" + str(args["arg"][0]) 
print "second parameter:" + str(args["arg"][1]) 
print "third parameter:" + str(args["arg"][2]) 
Cuestiones relacionadas