webentwicklung-frage-antwort-db.com.de

Argparse: Prüfen Sie, ob Argumente übergeben wurden

Mein Skript sollte einen Demo-Modus starten, wenn keine Parameter angegeben sind. Ich habe das versucht:

args = parser.parse_args()
if len(args) == 0:
    run_demo()
else:
    # evaluate args

Was eine *** TypeError: object of type 'Namespace' has no len() als args gibt, ist keine Liste. 

Wie würde ich erreichen, was ich will?

40
Framester

Wenn es Ihr Ziel ist, zu erkennen, wann kein Argument an den Befehl übergeben wurde, ist es falsch, dies über argparse zu tun (wie Ben nett darauf hingewiesen hat).

Denken Sie einfach! :-) Ich glaube, dass argparse sys.argv nicht entvölkert. Also, if not len(sys.argv) > 1, wurde vom Benutzer kein Argument angegeben.

61

mit argparse können Sie (in einem Namespace-Objekt) alle Variablen festlegen, die in den Argumenten erwähnt werden, die Sie dem Parser hinzugefügt haben, basierend auf Ihrer Spezifikation und der analysierten Befehlszeile. Wenn Sie einen Standard festlegen, haben diese Variablen diesen Standardwert, wenn sie nicht in der Befehlszeile angezeigt werden. Sie werden im Namespace-Objekt nicht fehlen. Und wenn Sie nicht einen Standard angeben, gibt es einen impliziten Standard von None. Das Überprüfen der Länge des Namespace-Objekts, wie auch immer Sie es schaffen, ist daher nicht sinnvoll, um zu überprüfen, ob Argumente analysiert wurden. es sollte immer die gleiche Länge haben.

Wenn Sie jedoch wissen, dass Sie eine Reihe von Argumenten ohne Standardwerte haben, und Sie möchten prüfen, ob einige von ihnen auf einen Wert gesetzt wurden, der nicht -None ist ... tun Sie das. Sie können ein Listenverständnis und die Funktion vars verwenden, um darüber zu blättern, ohne die Liste der Namen aus den add_argument-Aufrufen kopieren zu müssen, wie in der Antwort von Martijn gezeigt.

Etwas schwieriger wird es, wenn einige Ihrer Argumente über Standardwerte verfügen. Dies gilt insbesondere, wenn sie Standardwerte haben, die explizit in der Befehlszeile angegeben werden könnten (z. B. ein numerisches Argument mit dem Standardwert 0, sodass der Benutzer den Standardwert nicht erkennen kann) Bereitstellung von 0). In diesem Fall bin ich mir nicht sicher, ob es eine generelle Lösung gibt, die immer funktioniert, ohne dass die Argumente bekannt sind.

16
Ben

Wenn man wirklich die Argumentnummer benötigt (aus welchem ​​Grund auch immer) ... Ich fand diesen Code sehr hilfreich (weiß aber nicht, wie viel optimiert ist, und ich würde mich über jeden Kommentar freuen).

args = parser.parse_args()
print( len( vars(args) ) )

Diese Version zählt nur die -xx-Parameter und keinen weiteren übergebenen Wert.

Wenn man alles will (auch die Werte übergeben), dann benutze einfach len(sys.argv) wie zuvor erwähnt.

5
2dvisio

Verwenden Sie keine Raps. Verwenden Sie stattdessen einfach sys.argv. argparse erstellt einen Namespace, sodass Sie immer ein "Diktat" mit ihren Werten erhalten, abhängig davon, welche Argumente Sie beim Aufruf des Skripts verwendet haben.

Folgendes habe ich in der Vergangenheit gemacht: 

args = parser.parse_args()
if len(sys.argv) == 1:
    parser.print_help()
    sys.exit()
return args
4
edelatorre94

Nehmen wir folgendes Beispiel an, um Ihre Vollständigkeit zu erweitern:

#!/usr/bin/env python3

import argparse

...
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('input', nargs='?' action='store')
    parser.add_argument('-l', '--length', type=int, action='store')
    parser.add_argument('-v', '--verbose', action='store_true')
    args = parser.parse_args()
    if (args.input == None and args.length == None):
        parser.print_help()
    else:
        print(args)

if __== '__main__':
    main()

Ihr Namespace-Objekt, in diesem Beispiel von @Ben erwähnt, ist args. Aus den Zeichenfolgen in parser.add_argument wird eine Variable erstellt. Sie können über args.input oder args.length oder args.verbose darauf zugreifen. Sie können dies überprüfen, indem Sie print(args) ausführen, was in etwa Folgendes anzeigt:

Namespace(input=None, length=None, verbose=False)

da "verbose" auf "True" gesetzt ist, sind "input" und "length" lediglich Variablen, die nicht instanziiert werden müssen (keine Argumente angegeben).

Hilfreich kann auch group = parser.add_mutually_exclusive_group() sein, wenn Sie sicherstellen möchten, dass nicht zwei Attribute gleichzeitig bereitgestellt werden.

Weitere Informationen finden Sie unter:

2
AdamKalisz

Ich weiß, es ist ein alter Thread, aber ich habe eine direktere Lösung gefunden, die auch für andere nützlich sein könnte:

Sie können prüfen, ob Argumente übergeben wurden:

if any(vars(args).values()):
    # evaluate args

Oder, wenn keine Argumente übergeben wurden (beachten Sie den Operator not):

if not any(vars(args).values()):
    run_demo()

Erklärung:

  • parse_args() gibt ein "Namespace" -Objekt zurück, das jeden Argumentnamen und den zugehörigen Wert enthält. Beispiel: Namespace(arg1='myfile.txt', arg2='some/path/to/some/folder')

  • Wenn keine Argumente übergeben wurden, gibt parse_args() dasselbe Objekt mit allen Werten wie None zurück. Beispiel: Namespace(arg1=None, arg2=None)

Dieses Objekt kann jedoch nicht iteriert werden, sodass Sie vars() verwenden müssen, um es in ein dict umzuwandeln, damit wir auf die Werte zugreifen können.

Da wir nun ein dict zur Verfügung haben, können wir mit .values() alle Werte (in einem list) abrufen und das eingebaute any() Funktion zum Überprüfen, ob einer der Werte nicht None ist. Um es klarer zu machen: any() gibt False zurück, wenn es keinen einzelnen Wert gibt, der nicht None, False oder 0 Ist. (Überprüfen Sie die Dokumente als Referenz) in der Liste, die Sie eingegeben haben.

Ich hoffe es hilft.

1
Hyuri Pimentel

Ich habe das Konzept von 2dvisio erweitert, um Argumente ohne Null oder keine zu zählen:

vm_opts = parser.parse_args()
v = vars(vm_opts)
n_args = sum([ 1 for a in v.values( ) if a])
0
gerardw