Pasando listas enteras a python

Quiero pasar 2 listas de enteros como entrada a un progtwig de python.

Por ejemplo, (desde la línea de comandos)

python test.py --a 1 2 3 4 5 -b 1 2 

Los enteros en esta lista pueden variar de 1 a 50, la Lista 2 es un subconjunto de Lista1.
¿Alguna ayuda / sugerencia? ¿Es argparse el módulo correcto? ¿Alguna preocupación al usar eso?

Yo he tratado :

 import argparse if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('--a', help='Enter list 1 ') parser.add_argument('--b', help='Enter list 2 ') args = parser.parse_args() print (args.a) 

Puedes pasarlos como cadenas que convertir a listas. Puedes usar argparse o optparse .

 import argparse parser = argparse.ArgumentParser() parser.add_argument('--l1', type=str) parser.add_argument('--l2', type=str) args = parser.parse_args() l1_list = args.l1.split(',') # ['1','2','3','4'] 

Ejemplo: python prog.py --l1=1,2,3,4

Además, como línea puedes pasar algo como esto 1-50 y luego dividir en ‘-‘ y construir el rango. Algo como esto:

 import argparse parser = argparse.ArgumentParser() parser.add_argument('--l1', type=str, help="two numbers separated by a hyphen") parser.add_argument('--l2', type=str) args = parser.parse_args() l1_list_range = xrange(*args.l1.split('-')) # xrange(1,50) for i in l1_list_range: print i 

Ejemplo: python prog.py --l1=1-50

Lógica creo que puedes escribirte tú mismo. 🙂

argparse admite el parámetro nargs , que le indica cuántos parámetros come. Cuando nargs="+" acepta uno o más parámetros, por lo que puede pasar -b 1 2 3 4 y se asignará como una lista al argumento b

 # args.py import argparse p = argparse.ArgumentParser() # accept two lists of arguments # like -a 1 2 3 4 -b 1 2 3 p.add_argument('-a', nargs="+", type=int) p.add_argument('-b', nargs="+", type=int) args = p.parse_args() # check if input is valid set_a = set(args.a) set_b = set(args.b) # check if "a" is in proper range. if len(set_a - set(range(1, 51))) > 0: # can use also min(a)>=1 and max(a)<=50 raise Exception("set a not in range [1,50]") # check if "b" is in "a" if len(set_b - set_a) > 0: raise Exception("set b not entirely in set a") # you could even skip len(...) and leave just operations on sets # ... 

Así que puedes correr:

 $ python arg.py -a 1 2 3 4 -b 2 20 Exception: set b not entirely in set a $ python arg.py -a 1 2 3 4 60 -b 2 Exception: set a not in range [1,50] 

Y esto es válido:

 $ python arg.py -a 1 2 3 4 -b 2 3 

Esto funcionó para mí:

parser.add_argument('-i', '--ids', help="A comma separated list IDs", type=lambda x: x.split(','))

EDITAR:

Acabo de darme cuenta de que esto no responde realmente a la pregunta que se hace. Jakub tiene la solución correcta.

La forma en que optparse y argparse funcionan es que leen los argumentos desde la línea de comando, los argumentos se dividen por espacios en blanco, por lo que si desea ingresar su lista de enteros a través de la línea de comando, interactúe desde optparse o argparse ; puede hacerlo eliminando los espacios, o rodeando su argumento con " , ejemplo:

 > my_script.py --a "1 2 3 4 5" --b "1 2" 

o:

 > my_script.py --a 1,2,3,4,5 --b 1,2 

Su script entonces necesita convertir estas entradas en una lista real.

Usando la syntax argparse (muy similar para optparse ):

 # with spaces and " a_lst = [i for i in args.a.split(' ')] b_lst = [i for i in args.b.split(' ')] # without spaces and , a_lst = [i for i in args.a.split(',')] b_lst = [i for i in args.b.split(',')] 

Otra forma de hacerlo sería importando el módulo que desea ejecutar y pasando los objetos de la lista a una clase que se raw_input su código, o utilizando un bucle raw_input y input / input de input para recostackr la lista deseada.

Si los únicos argumentos son las listas y los separadores, puede hacerlo de manera relativamente simple:

 sa = sys.argv.index('-a') sb = sys.argv.index('-b') lista = [int(i) for i in sys.argv[sa+1:sb]] listb = [int(i) for i in sys.argv[sb+1:]] 

Añadir validación es fácil:

 aval = [i for i in lista if i>1 and i<50] if len(aval) < len(lista): print 'The -a list contains invalid numbers.' bval = [i for i in listb if i>1 and i<50] if len(bval) < len(listb): print 'The -b list contains invalid numbers.' 

Produciendo un mensaje de ayuda:

 if sys.argv[1] in ['-h', '-H'] or len(sys.argv) == 1: print "Usage:  -a [list of integers] -b [list of integers]" 

Sólo añadiendo este para completar. Me sorprendió no haber visto este enfoque.

 from argparse import Action, ArgumentParser class CommaSeparatedListAction(Action): def __call__(self, parser, namespace, values, option_string=None): setattr(namespace, self.dest, values.split(',')) parser = ArgumentParser() parser.add_argument('-l', action=CommaSeparatedListAction) print(parser.parse_args('-la,b,c,d'.split())) # Namespace(l=['a', 'b', 'c', 'd']) 

Este es solo un ejemplo básico, pero también puede agregar validación o transformar valores de alguna manera, como forzarlos a mayúsculas.

 from argparse import Action, ArgumentParser class UppercaseLetterCommaSeparatedListAction(Action): def __call__(self, parser, namespace, values, option_string=None): letters = values.split(',') for l in letters: self._validate_letter(parser, l) setattr( namespace, self.dest, list(map(lambda v: v.upper(), letters)) ) def _validate_letter(self, parser, letter): if len(letter) > 1 or not letter.isalpha(): parser.error('l must be a comma separated list of letters') parser = ArgumentParser() parser.add_argument('-l', action=UppercaseLetterCommaSeparatedListAction) print(parser.parse_args('-la,b,c,d'.split())) # Namespace(l=['A', 'B', 'C', 'D']) parser = ArgumentParser() parser.add_argument('-l', action=UppercaseLetterCommaSeparatedListAction) print(parser.parse_args('-la,bb,c,d'.split())) # usage: list.py [-h] [-l L] # list.py: error: l must be a comma separated list of letters parser = ArgumentParser() parser.add_argument('-l', action=UppercaseLetterCommaSeparatedListAction) print(parser.parse_args('-la,1,c,d'.split())) # usage: list.py [-h] [-l L] # list.py: error: l must be a comma separated list of letters