nargs - python3 argparse




Argparse-Option zum Übergeben einer Liste als Option (5)

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.

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"

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

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

Wenn Sie einen einzelnen Schalter verwenden nargs='+' , nehmen Sie mehrere Parameter, dann verwenden Sie nargs='+' . Wenn Ihr Beispiel '-l' tatsächlich Ganzzahlen verwendet:

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

Produziert

Namespace(list=[123, 234, 345, 456])
Namespace(list=[456])  # Attention!

Wenn Sie dasselbe Argument mehrmals angeben, ersetzt die Standardaktion ( 'store' ) die vorhandenen Daten.

Die Alternative besteht darin, die append Aktion zu verwenden:

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

Was produziert

Namespace(list=[123, 234, 345, 456])

Oder Sie können einen benutzerdefinierten Handler / eine benutzerdefinierte Aktion schreiben, um kommagetrennte Werte zu analysieren

-l 123,234,345 -l 456

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.





argparse