2012-11-12 16 views
11

Ich frage mich, ob es möglich ist, ein Positionsargument einem Argument mit einem optionalen Parameter folgen zu lassen. Im Idealfall gilt das letzte in die Befehlszeile eingegebene Argument immer für 'Testname'.argparse optionales Argument vor Positionsargument

Ich möchte, dass beide Aufrufe smoketest auf testname anwenden, aber die zweite führt zu einem Fehler.

>> python TAF.py -r 1.0 smoketest 
>> python TAF.py -r smoketest 
TAF.py: error: too few arguments 

Ich stelle fest, dass die Positions Argument an die Front bewegt sich in die richtige Verhalten des optionalen Parameter führen würde, aber das ist nicht ganz das Format die ich suche. Das Auswahlflag sieht wie eine attraktive Alternative aus, es löst jedoch einen Fehler aus, statt das nicht übereinstimmende Element zu ignorieren.

EDIT: Ich habe einen hacky Weg um diese gefunden. Wenn jemand eine bessere Lösung hat, würde ich es begrüßen.

import argparse 
parser = argparse.ArgumentParser(description='TAF') 
parser.add_argument('-r','--release',nargs='?',dest='release',default='trunk') 
parser.add_argument('testname',nargs=argparse.REMAINDER) 
args = parser.parse_args() 

if not args.testname: 
    args.testname = args.release 
    args.release = '' 

Antwort

3

Wie in der documentation erklärte:

'?'. Ein Argument wird, wenn möglich, von der Befehlszeile verbraucht und als einzelnes Element produziert. Wenn kein Befehlszeilenargument vorhanden ist, wird der Wert als Standardwert erstellt. Beachten Sie, dass es für optionale Argumente einen weiteren Fall gibt - die Optionszeichenfolge ist vorhanden , aber nicht gefolgt von einem Befehlszeilenargument. In diesem Fall wird der Wert von const erzeugt.

Also das gewünschte Verhalten ist nicht erreichbar mit '?'. Wahrscheinlich könntest du einen Hack mit argparse.Action schreiben und dich mit den vorherigen Ergebnissen einmischen. (1)

Ich denke, die bessere Lösung ist es, die Funktionalität dieser Option aufzuteilen. Machen Sie es zu einer Option, die ein Argument benötigt (aber die Option selbst ist optional) und fügen Sie eine Option ohne Argument hinzu, die das Release auf 'trunk' setzt. Auf diese Weise können Sie die gleichen Ergebnisse ohne jeden Hack erhalten. Ich denke auch, dass die Schnittstelle einfacher ist.

In Ihrem Beispiel:

python TAF.py -r smoketest 

Es ist ganz klar, dass smoketest wird als Argument an -r interpretiert werden. Zumindest nach Unix-Konventionen.

$ python TAF.py -r -- sometest 
Namespace(release=None, testname=['sometest']) #parsed result 

(1) Eine Idee, wie dies zu tun: Wenn Sie nargs='?' dann dem Benutzer Muss Verwendung -- behalten wollen überprüfen, ob die Option ein Argument hat. Wenn es eine Überprüfung hat, ob es ein gültiger Testname ist. Wenn dies der Fall ist, geben Sie testname ein und setzen Sie release auf den Standardwert. Sie müssen auch eine "Flagge" setzen, die Ihnen sagt, dass dieses Ding passiert ist.

Jetzt vor dem Analysieren sys.argv müssen Sie umleiten sys.stderr.Bei der Analyse müssen Sie SystemExit fangen, überprüfen Sie die stderr und sehen Sie, wenn der Fehler "zu wenig Argumente" war, überprüfen Sie, ob das Flag gesetzt war, wenn ja, den Fehler ignorieren und weiter ausführen, andernfalls sollten Sie den ursprünglichen Fehler stderr Nachricht und beenden.

Dieser Ansatz sieht nicht robust aus, und es ist wahrscheinlich fehlerhaft.

+0

Danke für die Antwort. Ich stimme zu, dass es sauber gemacht werden kann, indem man entweder ein Präfix für das Argument testname hinzufügt oder, wie ich bereits erwähnte, sie vor dem anderen Argument aufliste. –

Verwandte Themen