2012-11-12 18 views
11

Mi chiedevo se è possibile avere un argomento posizionale seguire un argomento con un parametro facoltativo. Idealmente l'ultimo argomento inserito nella riga di comando si applica sempre a "testname".argparse prima dell'argomento posizionale

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

Vorrei entrambe queste chiamate ad avere SmokeTest applicarsi a nometest, ma il secondo genera un errore.

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

mi rendo conto che spostare l'argomento posizionale al fronte comporterebbe il corretto comportamento del parametro opzionale, tuttavia questo non è del tutto il formato sto cercando. La bandiera delle scelte sembra un'alternativa interessante, tuttavia genera un errore invece di ignorare l'oggetto non abbinato.

MODIFICA: Ho trovato un modo per aggirare questo. Se qualcuno ha una soluzione migliore lo apprezzerei.

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

risposta

3

Come indicato nel documentation:

'?'. Un argomento verrà consumato dalla riga di comando, se possibile, e prodotto come singolo elemento. Se non è presente alcun argomento della riga di comando, verrà prodotto il valore predefinito. Si noti che per gli argomenti opzionali , esiste un caso aggiuntivo: la stringa di opzioni è presente ma non seguita da un argomento della riga di comando. In questo caso verrà prodotto il valore da const.

Quindi, il comportamento desiderato non è ottenibile utilizzando '?'. Probabilmente potresti scrivere qualche trucco usando argparse.Action e immischiarti con i risultati precedenti. (1)

Penso che la soluzione migliore sia quella di dividere la funzionalità di tale opzione. Rendilo un'opzione che richiede un argomento (ma l'opzione stessa è facoltativa) e aggiungi un'opzione senza argomento che imposta la versione su 'trunk'. In questo modo puoi ottenere gli stessi risultati senza alcun trucco. Inoltre penso che l'interfaccia sia più semplice.

Nel tuo esempio:

python TAF.py -r smoketest 

E 'abbastanza chiaro che smoketest sarà interpretato come un argomento per -r. Almeno seguendo le convenzioni Unix. Se si desidera mantenere nargs='?' quindi l'utente mosto uso --:

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

(1) Un'idea su come fare questo: verificare se l'opzione ha un argomento. Se ha un controllo se è un nome di prova valido. In tal caso, inserirla manualmente in testname e impostare release sul valore predefinito. Dovrai anche impostare una "bandiera" che ti dica che questa cosa è accaduta.

Ora, prima di analizzare sys.argv, è necessario reindirizzare sys.stderr.Quando esegui l'analisi devi prendere lo SystemExit, controllare lo stderr e vedere se l'errore era "troppo pochi argomenti", controllare se il flag era impostato, in tal caso ignorare l'errore e continuare a funzionare, altrimenti dovresti ristampare l'errore originale stderr messaggio e uscita.

Questo approccio non sembra robusto ed è probabilmente buggato.

+0

Grazie per la risposta. Sono d'accordo che può essere fatto in modo pulito sia aggiungendo un prefisso per l'argomento testname, o come ho detto solo elencandoli prima dell'altro argomento. –

Problemi correlati