2015-08-17 12 views
8

Sto usando arparse per aggiornare un config dict usando i valori specificati sulla riga di comando. Poiché voglio solo aggiornare i valori nella configurazione per cui un valore è stato esplicitamente menzionato sulla riga di comando.Come scoprire se l'argomento argparse è stato effettivamente specificato sulla riga di comando?

Pertanto, cerco di identificare gli argomenti non specificati controllando ciascuna azione se getattr(args, action.dest) == action.default o l'uguaglianza del tipo convertito arg. Poi aggiorno tutti i miei valori nel dict per il quale questo è falso.

Ma questo naturalmente fallisce, se specifichi esplicitamente un argomento sulla riga di comando che è lo stesso del mio argomento predefinito. C'è la possibilità di identificare questi argomenti esplicitamente citati con argparser o ho per identificarli manualmente in sys.argv?

Grazie!

Edit:

Per rendere più chiara le mie intenzioni. Ho un argomento come la seguente:

parser.add_argument('--test', default='meaningful_default')

e una configurazione simile

config = { 'test' : 'nondefault_val'}

Ora voglio aggiornare la configurazione solo con gli argomenti esplicitamente specificati. Confrontando i args attributi con i valori di default funziona fino a quando non mi specificare qualcosa di simile prog.py --test meaningful_default di aggiornare di nuovo il mio config con un valore che sembra appena essere anche il valore di default

+0

Perché? Se l'argomento è uguale al valore predefinito, perché è importante? –

+0

Se una delle risposte di seguito risolve il problema, è necessario accettarlo (fare clic sul segno di spunta accanto alla risposta appropriata). Questo fa due cose. Permette a tutti di sapere che il tuo problema è stato risolto in modo soddisfacente e dà la persona che ti aiuta a riconoscere l'assistenza. [Vedi qui] (http://meta.stackexchange.com/a/5235) per una spiegazione completa. –

risposta

3

Il parser mantiene un oggetto seen_actions insieme durante l'analisi (nel metodo _parse_known_args). Al termine dell'analisi, questo set viene confrontato con gli argomenti richiesti (quelli con required=True) e potrebbe generare un errore. Una variazione viene anche utilizzata con gruppi mutuamente esclusivi.

Ma questa variabile non è disponibile al di fuori di tale funzione. Quindi, a corto di una sorta di "gancio" che consente di applicare i propri test all'interno dell'azione parse_args, l'opzione migliore è quella di verificare i valori predefiniti. Oppure puoi guardare sys.argv[1:].

Il valore predefinito default è None. Questo è bello per questo scopo perché il tuo utente non può dare questo valore. Cioè, non c'è una stringa che converta in None (almeno non in nessuno dei normali metodi type).

+4

Dato che mi baso su valori di default non None, questa non è davvero una possibilità. Ora sto usando 'any ([arg.startswith (opzione) per arg in sys.argv [1:] per l'opzione in a.option_strings])' durante il loop su tutte le azioni. Questo sembra funzionare. – aem

+2

praticamente sconfigge lo scopo del parametro 'default ='. – n611x007

+1

Quando si arriva ai dettagli, la gestione dei valori predefiniti è sorprendentemente complessa. In questo caso, impostare opportunamente un valore predefinito e sapere se l'utente ha fornito un valore (anche quello predefinito), entra in conflitto. – hpaulj

0

Se si preferisce utilizzare argparse e poter specificare valori predefiniti, esiste una soluzione semplice che utilizza due parser.

I. Definire il parser principale e analizzare tutti i tuoi argomenti con valori di default adeguati:

parser = argparse.ArgumentParser() 
parser.add_argument('--test1', default='meaningful_default1') 
parser.add_argument('--test2', default='meaningful_default2') 
... 
args, unparsed = parser.parse_known_args() 

II. Definire un parser aux con argument_default=argparse.SUPPRESS per escludere argomenti non specificati. Aggiungere tutti gli argomenti dal parser principale, ma senza valori di default:

aux_parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS) 
for arg in vars(args): aux_parser.add_argument('--'+arg) 
cli_args, _ = aux_parser.parse_known_args() 

Questa non è una soluzione estremamente elegante, ma funziona bene con argparse e tutti i suoi benefici.

Problemi correlati