J'essaie de passer une liste comme argument à un programme en ligne de commande. Existe-t-il une option argparse
permettant de transmettre une liste en tant qu'option?
parser.add_argument('-l', '--list',
type=list, action='store',
dest='list',
help='<Required> Set flag',
required=True)
Le script s'appelle comme ci-dessous
python test.py -l "265340 268738 270774 270817"
TL; DR
Utilisez l'option nargs
ou le paramètre 'append'
de l'option action
(selon le comportement de l'interface utilisateur).
nargues
parser.add_argument('-l','--list', nargs='+', help='<Required> Set flag', required=True)
# Use like:
# python arg.py -l 1234 2345 3456 4567
nargs='+'
prend un ou plusieurs arguments, nargs='*'
prend zéro ou plus.
annexe
parser.add_argument('-l','--list', action='append', help='<Required> Set flag', required=True)
# Use like:
# python arg.py -l 1234 -l 2345 -l 3456 -l 4567
Avec append
, vous fournissez l’option plusieurs fois pour construire la liste.
N'utilisez pas type=list
!!! - Il n'y a probablement pas de situation où vous voudriez utiliser type=list
avec argparse
. Déjà.
Examinons plus en détail certaines des différentes manières dont on pourrait essayer de le faire, ainsi que le résultat final.
import argparse
parser = argparse.ArgumentParser()
# By default it will fail with multiple arguments.
parser.add_argument('--default')
# Telling the type to be a list will also fail for multiple arguments,
# but give incorrect results for a single argument.
parser.add_argument('--list-type', type=list)
# This will allow you to provide multiple arguments, but you will get
# a list of lists which is not desired.
parser.add_argument('--list-type-nargs', type=list, nargs='+')
# This is the correct way to handle accepting multiple arguments.
# '+' == 1 or more.
# '*' == 0 or more.
# '?' == 0 or 1.
# An int is an explicit number of arguments to accept.
parser.add_argument('--nargs', nargs='+')
# To make the input integers
parser.add_argument('--nargs-int-type', nargs='+', type=int)
# An alternate way to accept multiple inputs, but you must
# provide the flag once per input. Of course, you can use
# type=int here if you want.
parser.add_argument('--append-action', action='append')
# To show the results of the given option to screen.
for _, value in parser.parse_args()._get_kwargs():
if value is not None:
print(value)
Voici le résultat attendu:
$ python arg.py --default 1234 2345 3456 4567
...
arg.py: error: unrecognized arguments: 2345 3456 4567
$ python arg.py --list-type 1234 2345 3456 4567
...
arg.py: error: unrecognized arguments: 2345 3456 4567
$ # Quotes won't help here...
$ python arg.py --list-type "1234 2345 3456 4567"
['1', '2', '3', '4', ' ', '2', '3', '4', '5', ' ', '3', '4', '5', '6', ' ', '4', '5', '6', '7']
$ python arg.py --list-type-nargs 1234 2345 3456 4567
[['1', '2', '3', '4'], ['2', '3', '4', '5'], ['3', '4', '5', '6'], ['4', '5', '6', '7']]
$ python arg.py --nargs 1234 2345 3456 4567
['1234', '2345', '3456', '4567']
$ python arg.py --nargs-int-type 1234 2345 3456 4567
[1234, 2345, 3456, 4567]
$ # Negative numbers are handled perfectly fine out of the box.
$ python arg.py --nargs-int-type -1234 2345 -3456 4567
[-1234, 2345, -3456, 4567]
$ python arg.py --append-action 1234 --append-action 2345 --append-action 3456 --append-action 4567
['1234', '2345', '3456', '4567']
À emporter :
nargs
ou action='append'
nargs
peut être plus simple du point de vue de l'utilisateur, mais il peut ne pas être intuitif s'il existe des arguments de position car argparse
ne peut pas dire ce qui devrait être un argument de position et ce qui appartient à la nargs
; Si vous avez des arguments de position, alors action='append'
pourrait être un meilleur choix.nargs
reçoit '*'
, '+'
ou '?'
. Si vous fournissez un nombre entier (tel que 4
), le mélange des options avec nargs
et des arguments de positionnement ne posera aucun problème, car argparse
saura exactement combien de valeurs il faut attendre pour l'option.type=list
, car il renverra une liste de listes argparse
utilise la valeur de type
pour contraindre chaque argument donné vous avez choisi type
, pas l’agrégation de tous les arguments.type=int
(ou autre) pour obtenir une liste d'ints (ou autre)1: Je ne veux pas dire en général .. je veux dire utiliser des guillemets pour passer une liste à argparse
n'est pas ce que vous voulez.
Je préfère passer une chaîne délimitée que j'analyserai plus tard dans le script. Les raisons en sont la liste peut être de n'importe quel type int
ou str
, et parfois en utilisant nargs
Je rencontre des problèmes s'il existe plusieurs arguments facultatifs et arguments de position.
parser = ArgumentParser()
parser.add_argument('-l', '--list', help='delimited list input', type=str)
args = parser.parse_args()
my_list = [int(item) for item in args.list.split(',')]
Ensuite,
python test.py -l "265340,268738,270774,270817" [other arguments]
ou,
python test.py -l 265340,268738,270774,270817 [other arguments]
fonctionnera bien. Le délimiteur peut également être un espace, qui appliquerait des guillemets autour de la valeur de l'argument, comme dans l'exemple de la question.
En plus de nargs
, vous pouvez utiliser choices
si vous connaissez le liste à l'avance:
>>> parser = argparse.ArgumentParser(prog='game.py')
>>> parser.add_argument('move', choices=['rock', 'paper', 'scissors'])
>>> parser.parse_args(['rock'])
Namespace(move='rock')
>>> parser.parse_args(['fire'])
usage: game.py [-h] {rock,paper,scissors}
game.py: error: argument move: invalid choice: 'fire' (choose from 'rock',
'paper', 'scissors')
Utilisation de paramètre nargs dans la méthode add_argument de argparse
J'utilise nargs = '' comme paramètre add_argument. J'ai spécifiquement utilisé nargs = '' pour choisir les valeurs par défaut si je ne transmets aucun argument explicite
Y compris un extrait de code à titre d'exemple:
Exemple: temp_args1.py
Remarque: L'exemple de code ci-dessous est écrit en python3. En modifiant le format de l'instruction print, peut s'exécuter en python2
#!/usr/local/bin/python3.6
from argparse import ArgumentParser
description = 'testing for passing multiple arguments and to get list of args'
parser = ArgumentParser(description=description)
parser.add_argument('-i', '--item', action='store', dest='alist',
type=str, nargs='*', default=['item1', 'item2', 'item3'],
help="Examples: -i item1 item2, -i item3")
opts = parser.parse_args()
print("List of items: {}".format(opts.alist))
Remarque: je collecte plusieurs arguments de chaîne qui sont stockés dans la liste - opts.alist Si vous souhaitez une liste d'entiers, modifiez le paramètre type de parser.add_argument en int
Résultat d'exécution:
python3.6 temp_agrs1.py -i item5 item6 item7
List of items: ['item5', 'item6', 'item7']
python3.6 temp_agrs1.py -i item10
List of items: ['item10']
python3.6 temp_agrs1.py
List of items: ['item1', 'item2', 'item3']
Si vous souhaitez qu'un seul commutateur prenne plusieurs paramètres, utilisez nargs='+'
. Si votre exemple '-l' prend réellement des entiers:
a = argparse.ArgumentParser()
a.add_argument(
'-l', '--list', # either of this switches
nargs='+', # one or more parameters to this switch
type=int, # /parameters/ are ints
dest='list', # store in 'list'.
default=[], # since we're not specifying required.
)
print a.parse_args("-l 123 234 345 456".split(' '))
print a.parse_args("-l 123 -l=234 -l345 --list 456".split(' '))
Produit
Namespace(list=[123, 234, 345, 456])
Namespace(list=[456]) # Attention!
Si vous spécifiez le même argument plusieurs fois, l'action par défaut ('store'
) remplace les données existantes.
L'alternative consiste à utiliser l'action append
:
a = argparse.ArgumentParser()
a.add_argument(
'-l', '--list', # either of this switches
type=int, # /parameters/ are ints
dest='list', # store in 'list'.
default=[], # since we're not specifying required.
action='append', # add to the list instead of replacing it
)
print a.parse_args("-l 123 -l=234 -l345 --list 456".split(' '))
Qui produit
Namespace(list=[123, 234, 345, 456])
Ou vous pouvez écrire un gestionnaire/une action personnalisée pour analyser les valeurs séparées par des virgules afin de pouvoir effectuer les opérations suivantes:
-l 123,234,345 -l 456
Dans add_argument()
, type
n'est qu'un objet appelable qui reçoit une chaîne et retourne une valeur d'option.
import ast
def arg_as_list(s):
v = ast.literal_eval(s)
if type(v) is not list:
raise argparse.ArgumentTypeError("Argument \"%s\" is not a list" % (s))
return v
def foo():
parser.add_argument("--list", type=arg_as_list, default=[],
help="List of values")
Cela permettra de:
$ ./tool --list "[1,2,3,4]"
Peut-être la réponse la plus simple
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-l", "--tolist", help="input to list", action="store_true")
parser.add_argument("newlist", type=str, help="generate a list")
args = parser.parse_args()
if args.tolist:
print(args.newlist.split(" "))
Si vous avez une liste imbriquée dans laquelle les listes internes ont des types et des longueurs différents et que vous souhaitez conserver le type, par exemple,
[[1, 2], ["foo", "bar"], [3.14, "baz", 20]]
alors vous pouvez utiliser la solution proposée par @ sam-mason à cette question , ci-dessous:
from argparse import ArgumentParser
import json
parser = ArgumentParser()
parser.add_argument('-l', type=json.loads)
parser.parse_args(['-l', '[[1,2],["foo","bar"],[3.14,"baz",20]]'])
qui donne:
Namespace(l=[[1, 2], ['foo', 'bar'], [3.14, 'baz', 20]])