2012-11-12 8 views
11

Zastanawiam się, czy możliwe jest zastosowanie argumentu pozycyjnego po argumencie z opcjonalnym parametrem. Najlepiej, jeśli ostatni argument wprowadzony w linii poleceń będzie zawsze stosowany w odniesieniu do "testname".argparse opcjonalny argument przed argumentem pozycyjnym

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

Chciałbym, aby oba te wywołania miały być testowane, ale drugi powoduje błąd.

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

Zdaję sobie sprawę, że przesuwając pozycyjnym argumentu do przodu spowoduje prawidłowego zachowania opcjonalny parametr, jednak nie jest to całkiem format szukam. Flaga wyboru wygląda atrakcyjnie, ale zamiast ignorować niedopasowany element, generuje błąd.

EDYCJA: Znalazłem sposób hacky wokół tego. Jeśli ktokolwiek ma lepsze rozwiązanie, byłbym wdzięczny.

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

Odpowiedz

3

Jak stwierdzono w documentation:

'?'. Jeden argument zostanie zużyty z linii poleceń, jeśli to możliwe, i zostanie wyprodukowany jako pojedynczy element. Jeśli nie ma argumentu wiersza polecenia, zostanie wygenerowana wartość domyślna. Zauważ, że dla opcjonalnych argumentów występuje dodatkowy przypadek - ciąg opcji jest obecny , ale nie występuje po nim argument wiersza poleceń. W tym przypadku zostanie wygenerowana wartość ze stałej.

Takich zachowań nie można uzyskać za pomocą '?'. Prawdopodobnie mógłbyś napisać jakiś hack używając argparse.Action i mieszając się z poprzednimi wynikami. (1)

Myślę, że lepszym rozwiązaniem jest podział funkcjonalności tej opcji. Ustaw jako opcję wymagającą argumentu (ale opcja jest opcjonalna) i dodaj opcję bez argumentu, który ustawia wersję na 'trunk'. W ten sposób możesz uzyskać te same wyniki bez hackowania. Myślę również, że interfejs jest prostszy.

W przykładzie:

python TAF.py -r smoketest 

Jest dość oczywiste, że smoketest będą interpretowane jako argument do -r. Przynajmniej następujące konwencje unix. Jeśli chcesz zachować nargs='?' Następnie użytkownik musikorzystanie --:

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

(1) pomysł, jak to zrobić: Sprawdź, czy opcja ma argument. Jeśli ma jedną kontrolę, czy jest to poprawna nazwa testu. Jeśli tak, ręcznie wpisać testname i ustawić release na wartość domyślną. Musisz także ustawić "flagę", która mówi ci, że to się stało.

Teraz przed analizą sys.argv należy przekierować sys.stderr.Podczas wykonywania parsowania musisz złapać SystemExit, sprawdź stderr i sprawdź, czy błąd był "zbyt mało argumentów", sprawdź, czy flaga została ustawiona, jeśli tak, zignoruj ​​błąd i kontynuuj działanie, w przeciwnym razie powinieneś przedrukować do pierwotnego stderr błąd wiadomość i wyjdź.

Takie podejście nie wygląda dobrze i prawdopodobnie jest błędne.

+0

Dzięki za odpowiedź. Zgadzam się, że można to zrobić czysto zarówno poprzez dodanie prefiksu dla argumentu nazwa_testowa, lub jak wspomniałem tylko wymieniając je przed innym argumentem. –

Powiązane problemy