Verifica se sys.argv [x] è definito


Risposte:


64

Alla fine, la differenza tra try, excepte test len(sys.argv)non è poi così significativa. Sono entrambi un po 'hacker rispetto a argparse.

Questo mi viene in mente, tuttavia, come una sorta di argparse a basso budget:

arg_names = ['command', 'x', 'y', 'operation', 'option']
args = dict(zip(arg_names, sys.argv))

Potresti persino usarlo per generare un namedtuplecon valori impostati per impostazione predefinita None- tutto in quattro righe!

Arg_list = collections.namedtuple('Arg_list', arg_names)
args = Arg_list(*(args.get(arg, None) for arg in arg_names))

Nel caso in cui non hai familiarità namedtuple, è solo una tupla che agisce come un oggetto, permettendoti di accedere ai suoi valori usando la tup.attributesintassi invece della tup[0]sintassi.

Quindi la prima riga crea un nuovo namedtupletipo con valori per ciascuno dei valori in arg_names. La seconda riga passa i valori dal argsdizionario, utilizzando getper restituire un valore predefinito quando il nome dell'argomento specificato non ha un valore associato nel dizionario.


Amo Python sempre di più, tutto grazie a risposte come questa e Stack Overflow ovviamente! Peccato che non abbiamo una spiegazione delle ultime due righe. Credo che per i principianti sarebbe fantastico.
Goujon

2
Lo adoro! Facilmente la migliore soluzione che ho visto di questo problema. Per altri: non è stato immediatamente ovvio per me (newb) che: 1) il 'comando' passerà come primo argomento ogni volta e 2) puoi chiamare i risultati con argomenti [0] ecc.
Matt D

Questo è sicuramente bello, ma cosa c'è di complicato nel testare la lunghezza?
colorlace

1
@timwiz stavo parlando solo in confronto all'utilizzo di argparse. Tuttavia, in questi giorni, mi prendo a calci ogni volta che torno a una vecchia sceneggiatura e scopro di non aver usato argparse.
senderle

116

Controlla la lunghezza di sys.argv:

if len(sys.argv) > 1:
    blah = sys.argv[1]
else:
    blah = 'blah'

Alcune persone preferiscono l'approccio basato sulle eccezioni che hai suggerito (ad es. try: blah = sys.argv[1]; except IndexError: blah = 'blah'), Ma non mi piace così tanto perché non "scala" altrettanto bene (ad es., Quando vuoi accettare due o tre argomenti) e può potenzialmente nascondere errori (ad esempio, se si utilizza blah = foo(sys.argv[1]), ma si foo(...)solleva un IndexError, questo IndexErrorverrebbe ignorato).


1
Finché sei atomico al riguardo, non c'è nulla di cui preoccuparsi try, except. Aspetta solo il footuo argomento fino alla elseclausola.
senderle

3
Inoltre, una volta che stai pensando di ridimensionare, è ora di passare a argparse.
senderle

1
+1 su argparse. Ho argparse.pyin tutti i miei progetti da riga di comando.
David Wolever

2
@senderle: certo, se sei diligente, va bene. Ma nella mia esperienza la maggior parte dei programmatori non è diligente e mette tutta la logica nella tryclausola ... Quindi, dato che non è più difficile (e, IMO, un po 'più carina), preferisco controllare solo la lunghezza (inoltre, eviti che le persone sgridarti per aver utilizzato le eccezioni per il controllo del flusso).
David Wolever

2
@ David, sì, vedo il tuo punto. Sono un po 'un tryapologeta, devo ammetterlo. Sento solo che a volte esprime il mio intento più chiaramente di ifun'affermazione.
senderle

22

Un altro modo che non ho ancora visto elencato è impostare il valore della tua sentinella in anticipo. Questo metodo sfrutta la valutazione lenta di Python, in cui non è sempre necessario fornire elseun'istruzione. Esempio:

startingpoint = 'blah'
if len(sys.argv) >= 2:
  startingpoint = sys.argv[1]

Oppure, se stai usando la sintassi PAZZO, potresti usare l' operatore ternario di Python :

startingpoint = sys.argv[1] if len(sys.argv) >= 2 else 'blah'

1
La risposta dell'operatore ternario è ai miei occhi la più carina. Sono seduto qui a maledire silenziosamente il fatto che alcuni dei software che mantengo siano legati a Python 2.4, che non ce l'ha.
Richard Barrell

11

Lo uso - non fallisce mai:

startingpoint = 'blah'
if sys.argv[1:]:
   startingpoint = sys.argv[1]

Questo non è per controllare se definito. È più come definire se esiste, che non è lo stesso. Ho usato questo metodo anche per valutare le variabili di fallback, ma non è una risposta alla domanda attuale.
m3nda

@ erm3nda Posso rimuovere la startingpointvariabile dall'esempio, ma la domanda è l'assegnazione di una variabile di fallback, quindi ho fatto lo stesso.
anatoly techtonik

1
Se lo rimuovi otterrai un errore sulla variabile non definita. Ho letto di nuovo la domanda, e quello che si aspetta è che, una sostituzione variabile :) quindi va bene. Grazie per il consiglio di quella breve strada se sys.argv[1:]:. Funziona con argomenti posizionali mentre count no.
m3nda

10

È un normale elenco di Python. L'eccezione che potresti catturare per questo è IndexError, ma è meglio controllare solo la lunghezza.

if len(sys.argv) >= 2:
  startingpoint = sys.argv[1]
else:
  startingpoint = 'blah'

2

Una soluzione che funziona con la funzione integrata della mappa!

arg_names = ['command' ,'operation', 'parameter']
args = map(None, arg_names, sys.argv)
args = {k:v for (k,v) in args}

Quindi devi solo chiamare i tuoi parametri in questo modo:

if args['operation'] == "division":
    if not args['parameter']:
        ...
    if args['parameter'] == "euclidian":
        ...

1

Puoi semplicemente aggiungere il valore di argv [1] ad argv e quindi controllare se argv [1] non è uguale alla stringa che hai immesso Esempio:

from sys import argv
argv.append('SomeString')
if argv[1]!="SomeString":
            print(argv[1])

per quelli che mi hanno votato giù, vergogna a te, per non aver chiarito l'errore.
Hassan Abdul-Kareem,

Immagino sia perché è hacker. E se qualcuno passasse SomeString come argomento? Come usarlo se puoi accettare diciamo da 1 a 5 argomenti?
pbogut

Fantastico (ma comunque hackish) per impostare un valore predefinito nel caso in cui l'utente non fornisca l'argomento. Basta aggiungere e quindi utilizzare argv [1].
Felizett

1

Abbastanza vicino a ciò che l'originatore stava cercando di fare. Ecco una funzione che utilizzo:

def get_arg(index):
    try:
        sys.argv[index]
    except IndexError:
        return ''
    else:
        return sys.argv[index]

Quindi un utilizzo sarebbe qualcosa del tipo:

if __name__ == "__main__":
    banner(get_arg(1),get_arg(2))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.