Controlla se l'argomento opzionale argparse è impostato o meno


112

Vorrei verificare se un argomento argparse opzionale è stato impostato dall'utente o meno.

Posso controllare in sicurezza usando isset?

Qualcosa come questo:

if(isset(args.myArg)):
    #do something
else:
    #do something else

Funziona allo stesso modo per argomenti di tipo float / int / string?

Potrei impostare un parametro predefinito e controllarlo (ad esempio, impostare myArg = -1, o "" per una stringa, o "NOT_SET"). Tuttavia, il valore che alla fine desidero utilizzare viene calcolato solo più avanti nello script. Quindi lo avrei impostato su -1 come impostazione predefinita, quindi lo avrei aggiornato a qualcos'altro in seguito. Questo sembra un po 'goffo rispetto al semplice controllo se il valore è stato impostato dall'utente.


1
Quale sarebbe isset()(suggerimento: Python non è PHP)? Intendevi hasattr()invece, forse? Perché non configurare argparse per impostare invece un valore predefinito per un'opzione?
Martijn Pieters

@MartijnPieters - sì, vero. Quindi posso semplicemente controllare se (args.myArg): ...
Madeleine P. Vincent

Risposte:


146

Penso che gli argomenti opzionali (specificati con --) siano inizializzati Nonese non vengono forniti. Quindi puoi testare con is not None. Prova l'esempio di seguito:

import argparse as ap

def main():
    parser = ap.ArgumentParser(description="My Script")
    parser.add_argument("--myArg")
    args, leftovers = parser.parse_known_args()

    if args.myArg is not None:
        print "myArg has been set (value is %s)" % args.myArg

I test "non è nessuno" e "non è nessuno" funzionano esattamente come vorrei e mi aspetto. Grazie.
Madeleine P. Vincent

39
Sfortunatamente non funziona, quindi l'argomento ha il suo defaultvalore definito.
kcpr

6
Se vuoi impostare a default, puoi comunque impostare nargs='?'e fornire un constvalore, come descritto nella documentazione . Quando arg è assente, defaultviene usato, quando arg è dato senza valore, allora constviene usato, altrimenti viene usato il valore dato. Con solo defaulte nargs='?', defaultviene usato se non dato, Nonese dato senza valore, altrimenti il ​​valore dato.
Ioannis Filippidis

@IoannisFilippidis se usi action= "store_true"o action="store_const", const="yourconst"non puoi usare quell'argomento per memorizzare un altro valore. Questo non funzionerà quando si utilizzano i valori predefiniti. Nel mio ho rimosso tutti i valori predefiniti da argparser e gestito tutto all'interno di un'altra funzione in def defaults():cui mescolo ConfigParser, ArgumentParser e valori predefiniti nell'ordine che voglio
m3nda

@ erm3nda Non ho menzionato l'impostazione di un file action. La risposta non usa un file action. Le azioni che menzioni sono documentate per comportarsi in un modo specifico (come hai osservato). Non è però necessario definire un'azione.
Ioannis Filippidis

37

Come nota @Honza is Noneè un buon test. È l'impostazione predefinita defaulte l'utente non può darti una stringa che la duplica.

Puoi specificarne un altro default='mydefaultvaluee testarlo. Ma cosa succede se l'utente specifica quella stringa? Conta come ambientazione o no?

Puoi anche specificare default=argparse.SUPPRESS. Quindi se l'utente non utilizza l'argomento, non apparirà nello argsspazio dei nomi. Ma il test potrebbe essere più complicato:

args.foo # raises an AttributeError
hasattr(args, 'foo')  # returns False
getattr(args, 'foo', 'other') # returns 'other'

Internamente parsermantiene un elenco di seen_actionse lo utilizza per i test "obbligatori" e "mutuamente_esclusivi". Ma non è disponibile per te fuori parse_args.


22

Penso che usare l'opzione default=argparse.SUPPRESSabbia più senso. Quindi, invece di controllare se l'argomento è not None, si controlla se l'argomento è inlo spazio dei nomi risultante.

Esempio:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--foo", default=argparse.SUPPRESS)
ns = parser.parse_args()

print("Parsed arguments: {}".format(ns))
print("foo in namespace?: {}".format("foo" in ns))

Uso:

$ python argparse_test.py --foo 1
Parsed arguments: Namespace(foo='1')
foo in namespace?: True
L'argomento non viene fornito:
$ python argparse_test.py
Parsed arguments: Namespace()
foo in namespace?: False

Questo non funziona per me con Python 3.7.5 (Anaconda). Ottengo il risultatotestfoo.py: error: argument --foo: expected one argument
Mike Wise il

@MikeWise Se vuoi usare --foosenza un valore (cioè 1nel mio esempio), devi specificarlo nargs=0nella add_argumentfunzione.
Erasmus Cedernaes

Ho appena copiato e incollato il tuo codice come specificato nella risposta. Forse dovresti modificarlo? Ho finito per usare la action='store_true'risposta di seguito invece nel mio codice attuale.
Mike Wise,

@ MikeWise hai eseguito lo script come python argparse_test.py --foo 1?
Erasmus Cedernaes

11

Puoi controllare un flag passato facoltativamente con store_truee le store_falseopzioni di azione dell'argomento:

import argparse

argparser = argparse.ArgumentParser()
argparser.add_argument('-flag', dest='flag_exists', action='store_true')

print argparser.parse_args([])
# Namespace(flag_exists=False)
print argparser.parse_args(['-flag'])
# Namespace(flag_exists=True)

In questo modo, non devi preoccuparti di controllare tramite condizionale is not None. Devi semplicemente controllare Trueo False. Maggiori informazioni su queste opzioni nei documenti qui


1
questo non risolve per sapere se un argomento che ha un valore è impostato o meno. il problema principale qui è sapere se il valore args proviene da defaul = "" o è fornito dall'utente.
m3nda

5

Se il tuo argomento è posizionale (cioè non ha un prefisso "-" o "-", solo l'argomento, in genere un nome di file), puoi utilizzare il parametro nargs per farlo:

parser = argparse.ArgumentParser(description='Foo is a program that does things')
parser.add_argument('filename', nargs='?')
args = parser.parse_args()

if args.filename is not None:
    print('The file name is {}'.format(args.filename))
else:
    print('Oh well ; No args, no problems')

3

Ecco la mia soluzione per vedere se sto usando una variabile argparse

import argparse

ap = argparse.ArgumentParser()
ap.add_argument("-1", "--first", required=True)
ap.add_argument("-2", "--second", required=True)
ap.add_argument("-3", "--third", required=False) 
# Combine all arguments into a list called args
args = vars(ap.parse_args())
if args["third"] is not None:
# do something

Questo potrebbe fornire maggiori informazioni sulla risposta di cui sopra che ho usato e adattato per funzionare per il mio programma.


0

Per rispondere al commento di @ kcpr sulla risposta (attualmente accettata) di @Honza Osobne

Purtroppo non funziona, quindi l'argomento ha il suo valore predefinito definito.

si può prima verificare se l'argomento è stato fornito confrontandolo con l' Namespaceoggetto abd che fornisce l' default=argparse.SUPPRESSopzione (vedere le risposte di @ hpaulj e @Erasmus Cedernaes e questo documento python3 ) e se non è stato fornito, quindi impostarlo su un valore predefinito.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--infile', default=argparse.SUPPRESS)
args = parser.parse_args()
if 'infile' in args: 
    # the argument is in the namespace, it's been provided by the user
    # set it to what has been provided
    theinfile = args.infile
    print('argument \'--infile\' was given, set to {}'.format(theinfile))
else:
    # the argument isn't in the namespace
    # set it to a default value
    theinfile = 'your_default.txt'
    print('argument \'--infile\' was not given, set to default {}'.format(theinfile))

uso

$ python3 testargparse_so.py
argument '--infile' was not given, set to default your_default.txt

$ python3 testargparse_so.py --infile user_file.txt
argument '--infile' was given, set to user_file.txt

0

Molto semplice, dopo aver definito la variabile args con 'args = parser.parse_args ()' contiene anche tutti i dati delle variabili del sottoinsieme args. Per verificare se una variabile è impostata o no, assumendo che venga utilizzato 'action = "store_true" ...

if args.argument_name:
   # do something
else:
   # do something else
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.