python python3 Argparse-Option zum Übergeben einer Liste als Option




python3 argparse (6)

In add_argument() ist type nur ein aufrufbares Objekt, das eine Zeichenfolge empfängt und den Optionswert zurückgibt.

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

Dies ermöglicht:

$ ./tool --list "[1,2,3,4]"

Ich versuche, eine Liste als Argument an ein Befehlszeilenprogramm zu übergeben. Gibt es eine argparse Option, um eine Liste als Option zu übergeben?

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

Skript heißt wie unten

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

Ich bevorzuge es, eine begrenzte Zeichenfolge zu übergeben, die ich später im Skript analysieren werde. Die Gründe dafür sind; Die Liste kann von jedem Typ sein, int oder str , und manchmal nargs ich nargs , wenn Probleme mit mehreren optionalen Argumenten und Positionsargumenten auftreten.

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, das jedoch wie im Beispiel in der Frage Anführungszeichen um den Argumentwert erzwingt.


TL; DR

Verwenden Sie die Option nargs oder die Einstellung 'append' der nargs (abhängig davon, wie die Benutzeroberfläche sich verhalten soll).

Narben

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 mehr Argumente, nargs='*' benötigt 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 stellen Sie die Option mehrfach zur Verfügung, um die Liste aufzubauen.

Benutze nicht type=list !!! - Es gibt wahrscheinlich keine Situation, in der Sie type=list mit argparse . Je.

Werfen wir einen genaueren Blick auf einige der verschiedenen Möglichkeiten, wie man dies versuchen könnte, und auf das Endergebnis.

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

Takeaways :

  • Benutze nargs oder action='append'
    • nargs kann aus einer Benutzerperspektive nargs sein, aber es kann nicht intuitiv sein, wenn es Positionsargumente gibt, weil argparse nicht sagen kann, was ein Positionsargument sein soll und was zu den nargs ; Wenn Sie Positionsargumente haben action='append' kann action='append' Ende eine bessere Wahl sein.
    • Das obige ist nur wahr, wenn nargs '*' , '+' oder '?' . Wenn Sie eine Ganzzahl nargs (z. B. 4 ), ist es kein Problem, Optionen mit nargs und positionalen Argumenten zu argparse , da argparse genau weiß, 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 argparse unter der Haube den Wert des type , um jedes einzelne Argument, das Sie ausgewählt haben, zu argparse , nicht das Aggregat aller Argumente.
    • Sie können type=int (oder was auch immer) verwenden, um eine Liste von Ints (oder was auch immer) zu erhalten

1 : Ich meine nicht im Allgemeinen .. Ich meine mit Anführungszeichen, um eine Liste zu argparse ist nicht das, was Sie wollen.


Zusätzlich zu nargs möchten Sie möglicherweise eine 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')

Vielleicht die einfachste Antwort

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(" "))

Verwenden des nargs-Parameters in der add_argument-Methode von argparse

Ich benutze nargs = ' ' als Parameter add_argument. Ich habe speziell nargs = ' ' zur Auswahl von Standardwerten verwendet, wenn ich keine expliziten Argumente übergebe

Ein Code-Snippet als Beispiel einfügen:

Beispiel: temp_args1.py

Bitte beachten Sie: Der folgende Beispielcode ist in python3 geschrieben. Durch die Änderung der Druckanweisung Format kann 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 Integern möchten, ändern Sie den Parameter type in parser.add_argument in int

Ausführungsergebnis:

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




argparse