web-dev-qa-db-fra.com

Argparse: Vérifie si des arguments ont été passés

Mon script devrait démarrer en mode démo, quand aucun paramètre n'est donné. J'ai essayé ceci:

args = parser.parse_args()
if len(args) == 0:
    run_demo()
else:
    # evaluate args

Ce qui donne *** TypeError: object of type 'Namespace' has no len() comme args n'est pas une liste. 

Comment pourrais-je atteindre ce que je veux?

40
Framester

Si votre objectif est de détecter quand aucun argument n'a été donné à la commande, alors utiliser argparse est une mauvaise approche (comme Ben l'a gentiment fait remarquer).

Pensez simple! :-) Je crois que argparse ne dépeuple pas sys.argv. Donc, if not len(sys.argv) > 1, aucun argument n'a été fourni par l'utilisateur.

61

argparse vous permet de définir (à l'intérieur d'un objet Namespace) toutes les variables mentionnées dans les arguments que vous avez ajoutés à l'analyseur, en fonction de votre spécification et de la ligne de commande analysée. Si vous définissez une valeur par défaut, ces variables auront cette valeur par défaut si elles ne sont pas visibles sur la ligne de commande, elles ne seront pas absentes de l'objet Namespace. Et si vous ne spécifiez pas, une valeur implicite de None est définie. Donc, vérifier la longueur de l'objet Namespace, quel que soit le moyen utilisé, n'a pas de sens pour vérifier si des arguments ont été analysés; il devrait toujours avoir la même longueur.

Au lieu de cela, si vous savez que vous avez beaucoup d'arguments sans valeur par défaut et que vous voulez vérifier si l'un d'entre eux a été défini sur une valeur non -None, faites-le. Vous pouvez utiliser une compréhension de liste et la fonction vars pour les parcourir sans devoir dupliquer la liste des noms issus des appels add_argument, comme indiqué dans la réponse de Martijn.

Cela devient un peu plus compliqué si certains de vos arguments ont des valeurs par défaut, et plus encore s'ils ont des valeurs par défaut qui pourraient être explicitement fournies sur la ligne de commande (par exemple, un argument numérique dont la valeur par défaut est 0 rend impossible la détermination du paramètre par défaut par l'utilisateur fournissant 0). Dans ce cas, je ne suis pas sûr qu'il existe une solution générale qui fonctionne toujours sans connaître les arguments.

16
Ben

Si vous avez vraiment besoin du numéro d'argument (pour une raison quelconque) ..__, j'ai trouvé ce code très utile (mais je ne sais pas combien il est optimisé, et j'apprécierais tout commentaire à ce sujet).

args = parser.parse_args()
print( len( vars(args) ) )

Cette version ne compte que les paramètres -xx et pas toute valeur supplémentaire transmise.

Si on veut tout (aussi les valeurs passées), alors utilisez simplement len(sys.argv) comme mentionné précédemment.

5
2dvisio

Ne pas utiliser argparse. Au lieu de cela, utilisez simplement sys.argv. argparse crée un espace de noms afin qu'il vous donne toujours un "dict" avec leurs valeurs, en fonction des arguments que vous avez utilisés lorsque vous avez appelé le script.

Voici ce que j'ai fait dans le passé: 

args = parser.parse_args()
if len(sys.argv) == 1:
    parser.print_help()
    sys.exit()
return args
4
edelatorre94

Supposons que l'exemple suivant étende le vôtre par souci d'exhaustivité:

#!/usr/bin/env python3

import argparse

...
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('input', nargs='?' action='store')
    parser.add_argument('-l', '--length', type=int, action='store')
    parser.add_argument('-v', '--verbose', action='store_true')
    args = parser.parse_args()
    if (args.input == None and args.length == None):
        parser.print_help()
    else:
        print(args)

if __== '__main__':
    main()

Votre objet Namespace, mentionné par @Ben, dans cet exemple est args. Une variable est créée à partir des chaînes dans parser.add_argument. Vous pouvez y accéder via args.input ou args.length ou args.verbose. Vous pouvez le vérifier en exécutant print(args) qui affichera quelque chose comme ceci:

Namespace(input=None, length=None, verbose=False)

puisque verbose a la valeur True, s'il est présent, l'entrée et la longueur ne sont que des variables qui ne doivent pas être instanciées (aucun argument fourni).

group = parser.add_mutually_exclusive_group() peut également être utile si vous voulez vous assurer que deux attributs ne peuvent pas être fournis simultanément.

Pour plus de référence, veuillez vous référer à:

2
AdamKalisz

J'ai développé le concept de 2dvisio pour compter des arguments non nuls ou aucun:

vm_opts = parser.parse_args()
v = vars(vm_opts)
n_args = sum([ 1 for a in v.values( ) if a])
0
gerardw