TL; DR
Utilisez l' nargs
option ou le 'append'
paramètre de l' action
option (selon la façon dont vous souhaitez que l'interface utilisateur se comporte).
nargs
parser.add_argument('-l','--list', nargs='+', help='<Required> Set flag', required=True)
# Use like:
# python arg.py -l 1234 2345 3456 4567
nargs='+'
prend 1 ou plusieurs arguments, nargs='*'
zéro ou plus.
ajouter
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 constituer la liste.
Ne pas utiliser type=list
!!! - Il n'y a probablement pas de situation où vous voulez utiliser type=list
avec argparse
. Déjà.
Jetons un coup d'œil plus en détail sur certaines des différentes façons dont on pourrait essayer de le faire, et 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 la sortie à laquelle vous pouvez vous attendre:
$ 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']
Points à retenir :
- Utilisez
nargs
ouaction='append'
nargs
peut être plus simple du point de vue de l'utilisateur, mais cela peut ne pas être intuitif s'il y a des arguments positionnels parce argparse
qu'il ne peut pas dire ce qui devrait être un argument positionnel et ce qui appartient au nargs
; si vous avez des arguments positionnels, cela action='append'
peut être un meilleur choix.
- Ce qui précède est vrai que si
nargs
est donné '*'
, '+'
ou '?'
. Si vous fournissez un nombre entier (tel que 4
), il n'y aura aucun problème à mélanger les options avec nargs
et les arguments positionnels car argparse
ils sauront exactement combien de valeurs attendre pour l'option.
- N'utilisez pas de guillemets sur la ligne de commande 1
- Ne pas utiliser
type=list
, car il renverra une liste de listes
- Cela se produit parce que sous le capot
argparse
utilise la valeur de type
pour contraindre chaque argument donné individuel que vous avez choisi type
, et non l'agrégat de tous les arguments.
- Vous pouvez utiliser
type=int
(ou autre) pour obtenir une liste des entiers (ou autre)
1 : Je ne veux pas dire en général .. Je veux dire utiliser des guillemets pour passer une listeargparse
n'est pas ce que vous voulez.
type=list
option. Ne l'utilisez pas. Cela transforme une chaîne en liste, et donc les listes de listes.type
paramètre sur un autre objet. Par défaut, cette méthode renvoie une liste de chaînes.--
pourrait diviser les options par rapport aux arguments positionnels.prog --opt1 par1 ... -- posp1 posp2 ...
--
aide à comprendre cela comme le montre l'exemple dans mon commentaire précédent. Fournitures utilisateur IOW--
suivies de tous les arguments positionnels.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
oustr
, et parfois en utilisantnargs
je rencontre des problèmes s'il y a plusieurs arguments optionnels et arguments positionnels.Alors,
ou,
fonctionnera bien. Le délimiteur peut également être un espace, qui imposerait des guillemets autour de la valeur de l'argument comme dans l'exemple de la question.
la source
type
argument sur aulambda s: [int(time) for item in s.split(',')]
lieu du post-traitementargs.list
.int(time)
devrait l'êtreint(item)
. Mon exemple était une version simplifiée de ce que je fais généralement, où je vérifie beaucoup d'autres choses plutôt qu'un simple traitement. Mais pour répondre simplement à la question, je trouve moi aussi votre chemin plus élégant ..lambda items: list(csv.reader([items]))[0]
avec la bibliothèque csv standard est une version modifiée du commentaire de @chepner pour quiconque s'inquiète de l'entrée CSV arbitraire (réf: réponse de @adamk ).De plus
nargs
, vous voudrez peut-être utiliserchoices
si vous connaissez la liste à l'avance:la source
Utilisation du paramètre nargs dans la méthode add_argument d'Argparse
J'utilise nargs = ' ' comme paramètre add_argument. J'ai spécifiquement utilisé nargs = ' ' pour l'option de sélection des valeurs par défaut si je ne passe aucun argument explicite
Inclure un extrait de code comme exemple:
Exemple: temp_args1.py
Remarque: l' exemple de code ci-dessous est écrit en python3. En modifiant le format de l'instruction d'impression, peut s'exécuter en python2
Remarque: Je collecte plusieurs arguments de chaîne qui sont stockés dans la liste - opts.alist Si vous voulez une liste d'entiers, changez le paramètre de type sur parser.add_argument en int
Résultat d'exécution:
la source
temp_args1.py -i [item5 ,item6, item7]
et faire sortir la sortie sous forme de liste également (au lieu d'une liste imbriquée)Si vous avez l'intention de faire en sorte qu'un seul commutateur prenne plusieurs paramètres, vous l'utilisez
nargs='+'
. Si votre exemple '-l' prend en fait des entiers:Produit
Si vous spécifiez le même argument plusieurs fois, l'action par défaut (
'store'
) remplace les données existantes.L'alternative est d'utiliser l'
append
action:Qui produit
Ou vous pouvez écrire un gestionnaire / action personnalisé pour analyser les valeurs séparées par des virgules afin que vous puissiez faire
la source
Dans
add_argument()
,type
est juste un objet appelable qui reçoit une chaîne et renvoie une valeur d'option.Cela permettra de:
la source
Si vous avez une liste imbriquée où les listes internes ont différents types et longueurs 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 , présentée ci-dessous:
qui donne:
la source
Je veux gérer le passage de plusieurs listes, valeurs entières et chaînes.
Lien utile => Comment passer une variable Bash à Python?
L'ordre n'est pas important. Si vous voulez passer une liste faire aussi entre
"["
et"]
et séparer les utiliser une virgule.Alors,
Sortie =>
['my_string', '3', ['1', '2'], ['3', '4', '5']]
, lamy_args
variable contient les arguments dans l'ordre.la source
Je pense que la solution la plus élégante est de passer une fonction lambda à "type", comme mentionné par Chepner. De plus, si vous ne savez pas à l'avance quel sera le délimiteur de votre liste, vous pouvez également passer plusieurs délimiteurs à re.split:
la source
-l
dans l'exemple d'appel? D'où-n
venait-il?parser.add_argument('-l', '--list', type = lambda s: re.split('[ ,;]', s))
. Voici l'entrée:script.py -l abc xyz, abc\nxyz
. Enfin, voici le résultat:script.py: error: unrecognized arguments: xyz, abcnxyz