Le titre résume assez bien ce que j'aimerais que cela se produise.
Voici ce que j'ai, et bien que le programme n'explose pas sur un entier non positif, je souhaite que l'utilisateur soit informé qu'un entier non positif est fondamentalement un non-sens.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-g", "--games", type=int, default=162,
help="The number of games to simulate")
args = parser.parse_args()
Et la sortie:
python simulate_many.py -g 20
Setting up...
Playing games...
....................
Sortie avec un négatif:
python simulate_many.py -g -2
Setting up...
Playing games...
Maintenant, évidemment, je pourrais simplement ajouter un si pour déterminer if args.games
est négatif, mais j’étais curieux de savoir s’il existait un moyen de le piéger au niveau argparse
afin de tirer parti de l’impression automatique.
Idéalement, cela afficherait quelque chose de similaire à ceci:
python simulate_many.py -g a
usage: simulate_many.py [-h] [-g GAMES] [-d] [-l LEAGUE]
simulate_many.py: error: argument -g/--games: invalid int value: 'a'
Ainsi:
python simulate_many.py -g -2
usage: simulate_many.py [-h] [-g GAMES] [-d] [-l LEAGUE]
simulate_many.py: error: argument -g/--games: invalid positive int value: '-2'
Pour le moment je fais ça et je suppose que je suis heureux:
if args.games <= 0:
parser.print_help()
print "-g/--games: must be positive."
sys.exit(1)
Cela devrait être possible en utilisant type
. Vous aurez toujours besoin de définir une méthode qui décide cela pour vous:
def check_positive(value):
ivalue = int(value)
if ivalue <= 0:
raise argparse.ArgumentTypeError("%s is an invalid positive int value" % value)
return ivalue
parser = argparse.ArgumentParser(...)
parser.add_argument('foo', type=check_positive)
Ceci est fondamentalement juste un exemple adapté de la perfect_square
fonction dans le docs sur argparse
.
type
serait l'option recommandée pour gérer les conditions/contrôles, comme dans la réponse de Yuushi.
Dans votre cas spécifique, vous pouvez également utiliser le paramètre choices
si votre limite supérieure est également connue:
parser.add_argument('foo', type=int, choices=xrange(5, 10))
La manière rapide et sale, si vous avez un maximum prévisible et min pour votre argument, est d'utiliser choices
avec une plage
parser.add_argument('foo', type=int, choices=xrange(0, 1000))
Une alternative plus simple, en particulier si la sous-classe argparse.ArgumentParser
, Consiste à lancer la validation à partir de la méthode parse_args
.
Dans une telle sous-classe:
def parse_args(self, args=None, namespace=None):
"""Parse and validate args."""
namespace = super().parse_args(args, namespace) # super() works in Python 3
if namespace.games <= 0:
raise self.error('The number of games must be a positive integer.')
return namespace
Cette technique peut ne pas être aussi cool qu'un appelable personnalisé, mais elle fait le travail.
À propos de ArgumentParser.error(message)
:
Cette méthode imprime un message d'utilisation comprenant le message à l'erreur standard et termine le programme avec un code d'état de 2.
Crédit: réponse par jonatan