Utilisation de 'argparse.ArgumentError' en Python

J'aimerais utiliser l'exception ArgumentError dans le module argparse en Python, mais je ne vois pas comment l'utiliser. La signature indique qu'il doit être appelé en tant que ArgumentError (argument, message) , mais je ne peux pas comprendre quel argument devrait être. Je pense que cela devrait faire partie de l'objet analyseur, mais je n'ai trouvé aucune documentation à ce sujet.

35
Vous pouvez l'utiliser dans une classe Action personnalisée, comme le font les classes existantes. Mais je ne peux pas imaginer de raison de le faire en dehors de l'analyseur . Cela n'a rien de spécial, il ajoute simplement le nom Action au message d'erreur. Étudiez son utilisation dans le code.
ajouté l'auteur hpaulj, source

2 Réponses

De la la documentation source :

ArgumentError: l'exception déclenchée par les objets ArgumentParser lorsqu'il y a des erreurs avec les actions de l'analyseur. Les erreurs générées lors de l'analyse de la ligne de commande sont interceptées par ArgumentParser et émises sous forme de messages de ligne de commande.

Le paramètre argument du constructeur est l'objet Action à partir duquel l'exception est générée. Généralement, il n'est pas nécessaire de l'élever en dehors d'une sous-classe Action et, lors de la sous-classification, il n'est pas nécessaire de l'élever explicitement. vous générez généralement ValueError (ou ce qui convient) à la place.

Valeurs flottantes comprises entre 0 et 1

En ce qui concerne votre commentaire, vous ne souhaitez accepter que les valeurs à virgule flottante comprises entre 0 et 1. Vous devez pour cela utiliser la possibilité de définir des types personnalisés. Vous pouvez le faire par exemple comme ceci:

def percentFloat (string):
    value = float(string)
    if value < 0 or value > 1:
        raise argparse.ArgumentTypeError('Value has to be between 0 and 1')
    return value

parser = argparse.ArgumentParser()
parser.add_argument('test', type=percentFloat)
parser.parse_args()

Notez que ceci est également sûr contre les non-floats car float (string) lève un ValueError pour les non-floats, ce qui déclenche également une erreur de type invalide par le argparse module . ArgumentTypeError n'est qu'un moyen de spécifier un message d'erreur personnalisé.

Paramètres mutuellement exclusifs

For Paramètres mutuellement exclusifs, you should use argparse.add_mutually_exclusive_group.

Dépendance de paramètre

Dépendance de paramètre isn’t really something that should be done by the argument parser. For semantic details, you should instead simply do it yourself:

args = parser.parse_args()
if args.w and not args.p:
    parser.error('-p is required when -w is set.')

Vous pouvez utiliser ArgumentParser.error pour créer des paramètres personnalisés. message d'erreur qui va interrompre le programme et imprimer sur la console.

Mais bien sûr, dans une situation aussi fondamentale, il serait beaucoup plus logique de deviner implicitement -p si possible.

49
ajouté
Ce n'est pas juste. Si je viens d'envoyer la valeur, j'obtiens AttributeError: l'objet 'float' n'a pas d'attribut 'chaîne_option' .
ajouté l'auteur asmeurer, source
Et au fait, je veux l'utiliser parce que je veux vérifier le type de module que le module ne prend pas directement en charge. Par exemple, je veux une valeur à virgule flottante comprise entre 0 et 1. argparse vous permet de spécifier qu'il doit s'agir d'une valeur flottante, mais je dois vérifier manuellement la plage. Cela semble être la bonne erreur à émettre lorsque la valeur est fausse.
ajouté l'auteur asmeurer, source
Le vote négatif est parce que la réponse est fausse. ArgumentError (1.1, "Valeur hors limites") déclenche AttributeError, comme je l'ai mentionné ci-dessus. Cela doit être une sorte d'objet argparse interne, mais je ne peux pas trouver quoi. En passant, un autre exemple de ce que vous pouvez faire est de définir une dépendance non triviale aux arguments, ce que le module argparse ne prend pas directement en charge, à ma connaissance. Quelque chose comme l'option -w nécessite l'option -p , ou -n et -N sont mutuellement exclusives.
ajouté l'auteur asmeurer, source
Merci. Ce parser.error était ce que je cherchais.
ajouté l'auteur asmeurer, source
@asmeurer Edited ma réponse pour vous donner un exemple sur la façon de le faire.
ajouté l'auteur poke, source
Mis à jour ma réponse.
ajouté l'auteur poke, source

Bien que parser.error() soit ce que veulent la plupart des gens, il est également possible d’utiliser argparse.ArgumentError() (comme le demande la question.) Vous avez besoin d’une référence à l’argument, comme le bar_arg dans l'exemple ci-dessous:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--foo')
bar_arg = parser.add_argument('--bar')

args = parser.parse_args()
if args.bar == 'xyzzy':
    raise argparse.ArgumentError(bar_arg, "Can't be 'xyzzy'")

if args.foo == 'xyzzy':
    parser.error("Can't be 'xyzzy'")

Cela produira une sortie comme celle ci-dessous:

$ python argparse_test.py --foo xyzzy
usage: argparse_test.py [-h] [--foo FOO] [--bar BAR]
argparse_test.py: error: Can't be 'xyzzy'

$ python argparse_test.py --bar xyzzy
Traceback (most recent call last):
  File "argparse_test.py", line 10, in 
    raise argparse.ArgumentError(bar_arg, "Can't be 'xyzzy'")
argparse.ArgumentError: argument --bar: Can't be 'xyzzy'
11
ajouté
C'est un bon exemple de la façon dont l'utilisation de ArgumentError en dehors de parser est possible, mais probablement inférieure à l'utilisation de parser.error .
ajouté l'auteur hpaulj, source
Eh bien, si vous écrivez bien votre message d'erreur, alors vous serez sûr de mentionner quel commutateur est celui qui a provoqué l'infraction. La création d'une variable distincte pour chaque argument ajouté peut s'avérer très lourde ...
ajouté l'auteur Praveen, source
@hpaulj, oui, mais ArgumentError présente un avantage: il vous permet de savoir quel commutateur est celui qui a provoqué l'infraction.
ajouté l'auteur ukrutt, source
@Praveen C'est une question de préférence, je suppose. Moi-même, je préfère la variable à l'écriture "--foo" ne peut pas être "xyzzy" ", car je dois alors me rappeler le nom propre du commutateur (ce n'est pas nécessairement le même que l'attribut de args ). Mais honnêtement, je pense que parser.error() devrait inclure le nom du commutateur incriminé par défaut.
ajouté l'auteur ukrutt, source