Vérifiez si l'argument facultatif argparse est défini ou non

112

Je voudrais vérifier si un argument argparse facultatif a été défini par l'utilisateur ou non.

Puis-je vérifier en toute sécurité en utilisant isset?

Quelque chose comme ça:

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

Cela fonctionne-t-il de la même manière pour les arguments de type float / int / string?

Je pourrais définir un paramètre par défaut et le vérifier (par exemple, définir myArg = -1, ou "" pour une chaîne, ou "NOT_SET"). Cependant, la valeur que je souhaite finalement utiliser n'est calculée que plus tard dans le script. Je le définirais donc sur -1 par défaut, puis je le mettrais à jour à autre chose plus tard. Cela semble un peu maladroit en comparaison avec le simple fait de vérifier si la valeur a été définie par l'utilisateur.

Madeleine P. Vincent
la source
1
Que serait isset()(indice: Python n'est pas PHP)? Voulez-vous dire à la hasattr()place, peut-être? Pourquoi ne pas configurer argparse pour définir une valeur par défaut pour une option à la place?
Martijn Pieters
@MartijnPieters - oui, c'est vrai. Alors puis-je simplement vérifier si (args.myArg): ...
Madeleine P. Vincent

Réponses:

146

Je pense que les arguments optionnels (spécifiés avec --) sont initialisés Nones'ils ne sont pas fournis. Vous pouvez donc tester avec is not None. Essayez l'exemple ci-dessous:

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
Honza Osobne
la source
Les tests "is None" et "is not None" fonctionnent exactement comme je le voudrais et je m'y attendais. Merci.
Madeleine P. Vincent
39
Malheureusement cela ne fonctionne pas alors l'argument a sa defaultvaleur définie.
kcpr
6
Si vous souhaitez définir a default, vous pouvez toujours définir nargs='?'et fournir une constvaleur, comme décrit dans la documentation . Quand arg est absent, defaultest utilisé, quand arg est donné sans valeur, alors constest utilisé, sinon la valeur donnée est utilisée. Avec seulement defaultet nargs='?', defaultest utilisé s'il n'est pas donné, Nones'il est donné sans valeur, sinon la valeur donnée.
Ioannis Filippidis
@IoannisFilippidis si vous utilisez action= "store_true"ou action="store_const", const="yourconst"ne pouvez pas utiliser cet argument pour stocker une autre valeur. Cela ne fonctionnera pas lors de l'utilisation des valeurs par défaut. Dans le mien, j'ai supprimé toutes les valeurs par défaut d'argparser et géré tout dans une autre fonction def defaults():où je mélange ConfigParser, ArgumentParser et les valeurs par défaut dans l'ordre que je veux
m3nda
@ erm3nda Je n'ai pas mentionné la création d'un fichier action. La réponse n'utilise pas de action. Les actions que vous mentionnez sont documentées pour se comporter d'une manière spécifique (comme vous l'avez observé). Il n'est cependant pas nécessaire de définir une action.
Ioannis Filippidis
37

Comme le note @Honza, is Nonec'est un bon test. C'est la valeur par défaut default, et l'utilisateur ne peut pas vous donner une chaîne qui la duplique.

Vous pouvez en spécifier un autre default='mydefaultvalueet le tester. Mais que faire si l'utilisateur spécifie cette chaîne? Est-ce que cela compte ou non?

Vous pouvez également spécifier default=argparse.SUPPRESS. Ensuite, si l'utilisateur n'utilise pas l'argument, il n'apparaîtra pas dans l' argsespace de noms. Mais des tests qui pourraient être plus compliqués:

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

En interne, le parsergarde une liste de seen_actions, et l'utilise pour les tests «obligatoires» et «mutuellement_exclusifs». Mais il n'est pas disponible pour vous en dehors de parse_args.

hpaulj
la source
22

Je pense que l'utilisation de l'option default=argparse.SUPPRESSest la plus logique. Ensuite, au lieu de vérifier si l'argument est not None, on vérifie si l'argument est inl'espace de noms résultant.

Exemple:

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))

Usage:

$ python argparse_test.py --foo 1
Parsed arguments: Namespace(foo='1')
foo in namespace?: True
L'argument n'est pas fourni:
$ python argparse_test.py
Parsed arguments: Namespace()
foo in namespace?: False
Erasmus Cedernaes
la source
Cela ne fonctionne pas pour moi sous Python 3.7.5 (Anaconda). J'obtiens le résultattestfoo.py: error: argument --foo: expected one argument
Mike Wise le
@MikeWise Si vous souhaitez utiliser --foosans valeur (c'est- 1à- dire dans mon exemple), vous devez spécifier nargs=0dans la add_argumentfonction.
Erasmus Cedernaes le
Je viens de copier et coller votre code comme spécifié dans la réponse. Peut-être devriez-vous le modifier? J'ai fini par utiliser la action='store_true'réponse ci-dessous à la place dans mon code réel.
Mike Wise le
@MikeWise as-tu exécuté le script en tant que python argparse_test.py --foo 1?
Erasmus Cedernaes le
11

Vous pouvez vérifier un indicateur éventuellement passé avec store_trueet store_falsedes options d'action d'argument:

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)

De cette façon, vous n'avez pas à vous soucier de la vérification par condition is not None. Vous vérifiez simplement Trueou False. En savoir plus sur ces options dans la documentation ici

Harry Sadler
la source
1
cela ne résout pas de savoir si un argument qui a une valeur est défini ou non. le problème principal ici est de savoir si la valeur args provient de defaul = "" ou si elle est fournie par l'utilisateur.
m3nda
5

Si votre argument est positionnel (c'est-à-dire qu'il n'a pas de préfixe "-" ou "-", juste l'argument, généralement un nom de fichier), vous pouvez utiliser le paramètre nargs pour ce faire:

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')
yPhil
la source
3

Voici ma solution pour voir si j'utilise une variable 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

Cela pourrait donner un meilleur aperçu de la réponse ci-dessus que j'ai utilisée et adaptée pour travailler pour mon programme.

C. Radford
la source
0

Afin de répondre au commentaire de @ kcpr sur la réponse (actuellement acceptée) de @Honza Osobne

Malheureusement, cela ne fonctionne pas, alors l'argument a sa valeur par défaut définie.

on peut d'abord vérifier si l'argument a été fourni en le comparant à l' Namespaceobjet abd fournissant l' default=argparse.SUPPRESSoption (voir les réponses de @ hpaulj et @Erasmus Cedernaes et ce document python3 ) et s'il n'a pas été fourni, puis définissez-le sur une valeur par défaut.

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))

Usage

$ 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
calocèdre
la source
0

Très simple, après avoir défini la variable args par 'args = parser.parse_args ()', elle contient également toutes les données des variables du sous-ensemble args. Pour vérifier si une variable est définie ou non en supposant que 'action = "store_true" est utilisé ...

if args.argument_name:
   # do something
else:
   # do something else
vatsa287
la source