784 Stimmen

Wie kann ich eine Liste als Kommandozeilenargument mit argparse übergeben?

Ich versuche, eine Liste als Argument an ein Befehlszeilenprogramm zu übergeben. Gibt es eine argparse Option zur Übergabe einer Liste als Option?

parser.add_argument('-l', '--list',
                      type=list, action='store',
                      dest='list',
                      help='<Required> Set flag',
                      required=True)

Das Skript wird wie folgt aufgerufen

python test.py -l "265340 268738 270774 270817"

1560voto

SethMMorton Punkte 40575

KURZANTWORT

Verwenden Sie die nargs Option oder die Option 'append' Einstellung der action (je nachdem, wie Sie das Verhalten der Benutzeroberfläche wünschen).

nargs

parser.add_argument('-l','--list', nargs='+', help='<Required> Set flag', required=True)
# Use like:
# python arg.py -l 1234 2345 3456 4567

nargs='+' benötigt 1 oder mehrere Argumente, nargs='*' nimmt null oder mehr.

anhängen.

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

Mit append Sie bieten die Möglichkeit, die Liste mehrfach zu erstellen.

Verwenden Sie nicht type=list !!! - Es gibt wahrscheinlich keine Situation, in der Sie die type=list con argparse . Niemals.


LANGE ANTWORT

Schauen wir uns einige der verschiedenen Möglichkeiten, wie man dies erreichen kann, und das Endergebnis genauer an.

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)

Hier ist die Ausgabe, die Sie erwarten können:

$ 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']

Mitbringsel :

  • Verwenden Sie nargs ou action='append'
    • nargs kann aus Sicht des Benutzers einfacher sein, aber es kann unintuitiv sein, wenn es Positionsargumente gibt, weil argparse kann nicht sagen, was ein Positionsargument sein soll und was zum nargs Wenn Sie positionale Argumente haben, dann action='append' könnte sich als die bessere Wahl erweisen.
    • Die obige Aussage trifft nur zu, wenn nargs ist gegeben '*' , '+' , oder '?' . Wenn Sie eine ganzzahlige Zahl angeben (z. B. 4 ), dann ist es kein Problem, die Optionen mit nargs und positionelle Argumente, weil argparse weiß genau, wie viele Werte für die Option zu erwarten sind.
  • Verwenden Sie keine Anführungszeichen in der Befehlszeile 1
  • Verwenden Sie nicht type=list da es eine Liste von Listen zurückgibt
    • Dies geschieht, weil unter der Haube argparse verwendet den Wert von type zu erzwingen jedes einzelne angegebene Argument Sie Ihr gewähltes type und nicht die Gesamtheit aller Argumente.
    • Sie können verwenden type=int (oder was auch immer), um eine Liste von Ints (oder was auch immer) zu erhalten

1 : Ich meine nicht im Allgemeinen Ich meine die Verwendung von Anführungszeichen für eine Liste übergeben an argparse ist nicht das, was Sie wollen.

150voto

dojuba Punkte 1989

Ich ziehe es vor, eine abgegrenzte Zeichenkette zu übergeben, die ich später im Skript auswerte. Die Gründe dafür sind; die Liste kann von jedem Typ sein int ou str und manchmal auch mit nargs Ich stoße auf Probleme, wenn es mehrere optionale Argumente und Positionsargumente gibt.

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(',')]

Dann,

python test.py -l "265340,268738,270774,270817" [other arguments]

oder,

python test.py -l 265340,268738,270774,270817 [other arguments]

wird gut funktionieren. Das Trennzeichen kann auch ein Leerzeichen sein, was allerdings Anführungszeichen um den Argumentwert erzwingen würde, wie in dem Beispiel in der Frage.

Oder Sie können einen Lambda-Typ verwenden, wie in den Kommentaren von Chepner vorgeschlagen:

parser.add_argument('-l', '--list', help='delimited list input', 
    type=lambda s: [int(item) for item in s.split(',')])

22voto

Martin Thoma Punkte 105621

Zusätzlich zu nargs können Sie Folgendes verwenden choices wenn Sie die Liste im Voraus kennen:

>>> 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')

19voto

Py_minion Punkte 1927

Verwendung von nargs-Parameter in der Methode add_argument von argparse

Ich benutze nargs='*' als Parameter add_argument. Ich habe speziell nargs='*' die Option, Standardwerte zu wählen, wenn ich keine expliziten Argumente übergebe

Mit einem Codeschnipsel als Beispiel:

Beispiel: temp_args1.py

Bitte beachten: Der folgende Beispielcode ist in Python 3 geschrieben. Durch Änderung des Druckanweisungsformats kann er in Python2 ausgeführt werden

#!/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))

Hinweis: Ich sammle mehrere String-Argumente, die in der Liste gespeichert werden - opts.alist Wenn Sie eine Liste von Ganzzahlen wünschen, ändern Sie den Parameter type in parser.add_argument a int

Ergebnis der Ausführung:

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']

15voto

lunguini Punkte 876

JSON-Liste Lösung

Eine gute Möglichkeit, Listen (auch Dicts) über die Kommandozeile zu übergeben, ist die Verwendung von json .

# parse_list.py
import argparse
import json

parser = argparse.ArgumentParser()
# note type arg, used to load json string
parser.add_argument('-l', '--list', type=json.loads)
args = parser.parse_args()
print(args.list)

Beispiel für die Verwendung

$ python parse_list.py -l "[265340, 268738, 270774, 270817]"
[265340, 268738, 270774, 270817]

Edit: Ich habe den Verbesserungsvorschlag von Katu um den separaten Parsing-Schritt zu entfernen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X