Je veux passer 2 listes d'entiers en entrée d'un programme python.
Par exemple, (à partir de la ligne de commande)
python test.py --a 1 2 3 4 5 -b 1 2
Les nombres entiers dans cette liste peuvent aller de 1 à 50, la liste 2 étant un sous-ensemble de List1.
Avez-vous de l'aide/des suggestions? Est-ce que argparse
est le bon module? Des préoccupations en utilisant cela?
J'ai essayé :
import argparse
if __== '__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)
Vous pouvez les transmettre sous forme de chaînes que de convertir en listes. Vous pouvez utiliser argparse ou 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']
Exemple: python prog.py --l1=1,2,3,4
En outre, en tant que ligne, vous pouvez passer quelque chose comme ceci 1-50, puis vous séparer de "-" et construire une plage. Quelque chose comme ça:
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
Exemple: python prog.py --l1=1-50
Je pense que vous pouvez écrire vous-même. :)
argparse
supporte nargs
paramètre, qui vous indique le nombre de paramètres qu’il mange. Lorsque nargs="+"
il accepte un ou plusieurs paramètres, vous pouvez donc passer -b 1 2 3 4
et il sera affecté en tant que liste à l'argument 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
# ...
Pour que vous puissiez courir:
$ 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]
Et ceci est valable:
$ python arg.py -a 1 2 3 4 -b 2 3
Cela a fonctionné pour moi:
parser.add_argument('-i', '--ids', help="A comma separated list IDs", type=lambda x: x.split(','))
MODIFIER:
Je viens de me rendre compte que cela ne répond pas vraiment à la question posée. Jakub a la bonne solution.
La manière dont optparse
et argparse
work est qu'ils lisent les arguments à partir de la ligne de commande, les arguments étant divisés par un espace, si vous voulez entrer votre liste d'entiers via la ligne de commande, utilisez optparse
ou argparse
- vous pouvez le faire en supprimant les espaces ou en entourant votre argument avec "
, exemple:
> my_script.py --a "1 2 3 4 5" --b "1 2"
ou:
> my_script.py --a 1,2,3,4,5 --b 1,2
Votre script doit ensuite convertir ces entrées en une liste réelle.
Utilisation de argparse
syntax (très similaire pour 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(',')]
Une autre façon de procéder consiste à importer le module que vous souhaitez exécuter et à transmettre les objets de liste à une classe qui traite votre code, ou à l'aide d'une boucle while et raw_input
/ input
à collecter. la liste souhaitée.
Si les arguments seulement sont les listes et les séparateurs, vous pouvez le faire relativement simplement:
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:]]
Ajouter une validation est facile:
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.'
Produire un message d'aide:
if sys.argv[1] in ['-h', '-H'] or len(sys.argv) == 1:
print "Usage: <name> -a [list of integers] -b [list of integers]"
Juste en ajoutant celui-ci pour la complétude. J'ai été surpris de ne pas voir cette approche.
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('-l a,b,c,d'.split()))
# Namespace(l=['a', 'b', 'c', 'd'])
Ceci n’est qu’un exemple élémentaire, mais vous pouvez également ajouter une validation ou transformer des valeurs, telles que les forcer en majuscules.
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('-l a,b,c,d'.split()))
# Namespace(l=['A', 'B', 'C', 'D'])
parser = ArgumentParser()
parser.add_argument('-l', action=UppercaseLetterCommaSeparatedListAction)
print(parser.parse_args('-l a,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('-l a,1,c,d'.split()))
# usage: list.py [-h] [-l L]
# list.py: error: l must be a comma separated list of letters