2013-10-10 10 views
5

Ho usato principalmente argparse per creare script da riga di comando in python, e l'idioma che uso generalmente è che assegno gli argomenti come attributi di un oggetto, quindi analizzarli singolarmente su una variabile che corrisponde al loro nome attributo. Questo sembra un po 'ripetitivo. C'è un modo per assegnarli tutti nello spazio dei nomi globale e tagliare la fase di assegnazione; o come spesso accade quando qualche comportamento di pitone sembra controintuitivo per me, può un saggio esperto di Python sottolineare che esiste una buona ragione per cui non dovrei farlo o voglio farlo?Python argparse parse_args nel namespace globale (o un motivo questa è una cattiva idea)

Quello che ho ora è questo:

if __name__ == "__main__": 
    parser = argparse.ArgumentParser() 
    parser.add_argument("--db",type=str, dest='db', nargs='?', default="test") 
    parser.add_argument("--collection",type=str, dest='collection', nargs='?', help="Collection, default is test", default="test") 
    args = parser.parse_args() 
    db = args.db     # gross! 
    collection = args.collection # yuck! 
    print(db) 
    print(collection) 

Quello che mi piacerebbe questo è:

if __name__ == "__main__": 
    parser = argparse.ArgumentParser() 
    parser.add_argument("--db",type=str, dest='db', nargs='?', default="test") 
    parser.add_argument("--collection",type=str, dest='collection', nargs='?', help="Collection, default is test", default="test") 
    parser.SUPER_parse_args() # now, db and collection are already in the namespace! 
    print(db) 
    print(collection) 

Non sembra un gran che, quando ho solo 2 argomenti, ma se io ne ho circa 10, raddoppiando i passi dell'assegnazione, dove rinominare nel namespace globale gli attributi che già esistono nell'oggetto args, inizia a infastidirmi.

+6

no. Non farlo. Io userei 'args' direttamente invece. –

+0

@MartijnPieters, tu eri esattamente uno dei saggi esperti di pitone che speravo potessero pesare su questo. – Mittenchops

risposta

6

È possibile farlo usando globals:

globals().update(args.__dict__) 

tuttavia, è davvero * non dovrebbe farlo. Dallo zen di python,

Gli spazi dei nomi sono una delle grandi idee - ne facciamo di più!

io eco quello @Martijn ha detto nel suo commento:

non lo fanno. Non farlo. Vorrei usare direttamente args.

Tenere le cose ben separate come è possibile. Rende il codice più manutenibile e più facile da capire.

+0

Capisco. Figo, grazie. La logica è solo per il fatto che avere variabili definite globalmente e al di fuori di args significa che è più probabile che si scontrino con cose nuove? Se è così, l'aggiornamento di globals come questo è davvero peggio del semplice script python unico in cui le variabili sono comunque definite nell'ambito globale? L'idea che i piccoli script si trasformino inevitabilmente in grandi script che richiedono una gestione più intelligente dei namespace? – Mittenchops

+2

@Mittenchops - Questo fa parte di esso. Rende anche la sorgente molto più facile da leggere. 3 mesi dopo, quando hai bisogno di aggiornare il tuo script e ti vedi usare una variabile 'foo', ma quando provi a grep il sorgente,' foo' non è definito da nessuna parte, quindi inizi a grattarti la testa e ti chiedi come il tutto funziona. – mgilson

0

Per aggiungere sulla risposta di mgilson:

considerare l'utilizzo di locals().update(args.__dict__) invece; questo aggiornerà lo spazio dei nomi corrente piuttosto che lo spazio dei nomi globale.

È anche possibile farlo utilizzando i locals() o vars(). Vedi this Stack Overflow post per una bella spiegazione sulla differenza tra i due.

Sono un po 'in ritardo per Mittonchops, ma spero che questo aiuti gli altri.

+0

Non usare la gente del posto. Non funzionerà. :-). aggiornare la gente del luogo non è garantito che funzioni su qualsiasi implementazione di python e non funziona su CPython (a meno che tu non sia nel namespace globale nel qual caso 'locals() == globals()' comunque :-) – mgilson

0

Questo è quello che ho fatto. Aiuta in caso di collisione variabile ma non di manutenzione.

parser_args = parser.parse_args() 
if parser_args.verbose: 
    globals().update(argparse.Namespace(verbose=parser_args.verbose).__dict__) 
Problemi correlati