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.