Je voudrais utiliser argparse pour analyser les arguments de ligne de commande booléens écrits comme "--foo True" ou "--foo False". Par exemple:
my_program --my_boolean_flag False
Cependant, le code de test suivant ne fait pas ce que je voudrais:
import argparse
parser = argparse.ArgumentParser(description="My parser")
parser.add_argument("--my_bool", type=bool)
cmd_line = ["--my_bool", "False"]
parsed_args = parser.parse(cmd_line)
Malheureusement, parsed_args.my_bool
évalue à True
. C'est le cas même lorsque je change cmd_line
pour être ["--my_bool", ""]
, ce qui est surprenant, car bool("")
évalue à False
.
Comment puis - je obtenir argparse pour analyser "False"
, "F"
et leur minuscules variantes d'être False
?
python
boolean
argparse
command-line-parsing
SuperElectric
la source
la source
parser.add_argument('--feature', dest='feature', default=False, action='store_true')
. Cette solution vous garantira toujours unbool
type avec une valeurTrue
ouFalse
. (Cette solution a une contrainte: votre option doit avoir une valeur par défaut.)parser.add_argument('--feature', dest='feature', type=lambda x:bool(distutils.util.strtobool(x)))
. Lorsque l'option est utilisée, cette solution garantit unbool
type avec la valeurTrue
ouFalse
. Lorsque l'option n'est pas utilisée, vous obtiendrezNone
. (distutils.util.strtobool(x)
provient d'une autre question de stackoverflow )parser.add_argument('--my_bool', action='store_true', default=False)
Réponses:
Encore une autre solution utilisant les suggestions précédentes, mais avec l'erreur d'analyse "correcte" de
argparse
:Ceci est très utile pour effectuer des commutations avec des valeurs par défaut; par exemple
me permet d'utiliser:
et toujours utiliser une valeur par défaut (spécifique aux paramètres utilisateur). Un inconvénient (indirectement lié) à cette approche est que les `` nargs '' peuvent attraper un argument positionnel - voir cette question connexe et ce rapport de bug d'argparse .
la source
str2bool(v)
pourrait être remplacé parbool(distutils.util.strtobool(v))
. Source: stackoverflow.com/a/18472142/2436175if args.nice:
beacuse si l'argument est défini sur False, il ne passera jamais la condition. Si cela est vrai , alors il est peut - être préférable de retourner la liste de lastr2bool
fonction et la liste Définir commeconst
paramètre, comme celui - ci[True]
,[False]
. Corrigez-moi si je me trompeJe pense qu'une façon plus canonique de le faire est via:
et
argparse
prend bien en charge cette version:Bien sûr, si vous voulez vraiment la
--arg <True|False>
version, vous pouvez passerast.literal_eval
comme "type", ou fonction définie par l'utilisateur ...la source
type=bool
devrait fonctionner hors de la boîte (considérez les arguments positionnels!). Même lorsque vous spécifiez en outrechoices=[False,True]
, vous vous retrouvez avec à la fois "Faux" et "Vrai" considéré comme Vrai (en raison d'une conversion de chaîne en booléen?). Peut-être un problème connexebool()
fonction Python devrait faire ou de ce que argparse devrait acceptertype=fn
? Toutes lesargparse
vérificationsfn
sont appelables. Il s'attendfn
à prendre un argument de chaîne et à renvoyer une valeur. Le comportement defn
incombe au programmeur, nonargparse's
.Je recommande la réponse de mgilson mais avec un groupe mutuellement exclusif
afin que vous ne puissiez pas utiliser
--feature
et--no-feature
en même temps.et
mais non
Scénario:
Vous pouvez ensuite utiliser cet assistant si vous allez en définir plusieurs:
la source
add_argument
est appelé avecdest='feature'
.set_defaults
est appelé avecfeature=True
. Comprendre?--flag False
, une partie des réponses des SO devrait porter sur CE QU'elles essaient de résoudre, pas seulement sur COMMENT. Il ne devrait y avoir aucune raison de faire--flag False
ou d'--other-flag True
utiliser un analyseur personnalisé pour convertir la chaîne en booléen ..action='store_true'
etaction='store_false'
sont les meilleures façons d'utiliser les drapeaux booléens... can be “don’t do that”, but it should also include “try this instead”
qui (au moins pour moi) implique des réponses devrait être plus approfondie le cas échéant. Il y a certainement des moments où certains d'entre nous qui posent des questions peuvent bénéficier de conseils sur les meilleures / meilleures pratiques, etc. Répondre souvent "comme indiqué" ne fait souvent pas cela. Cela étant dit, votre frustration avec des réponses supposant souvent trop (ou incorrectement) est tout à fait valable.parser.set_defaults(feature=None)
help=
entrée pour cet argument, où devrait-il aller? Dans l'add_mutually_exclusive_group()
appel? Dans l'un ou les deuxadd_argument()
appels? Ailleurs?Voici une autre variante sans ligne / s supplémentaire pour définir les valeurs par défaut. Le booléen a toujours une valeur assignée afin qu'il puisse être utilisé dans des instructions logiques sans pré-vérifications.
la source
required=True
sinon vous obtiendrez toujours un argument True.python3 test.py --do-something False
échoue avecerror: unrecognized arguments: False
, donc il ne répond pas vraiment à la question.bon mot:
la source
type=lambda x: (str(x).lower() in ['true','1', 'yes'])
Il semble y avoir une certaine confusion quant à ce que
type=bool
ettype='bool'
pourrait signifier. Doit-on (ou les deux) signifier 'exécuter la fonctionbool()
, ou' retourner un booléen '? En l'état, celatype='bool'
ne veut rien dire.add_argument
donne une'bool' is not callable
erreur, comme si vous l'avez utilisétype='foobar'
, outype='int'
.Mais
argparse
a un registre qui vous permet de définir des mots clés comme celui-ci. Il est principalement utilisé pouraction
, par exemple, `action = 'store_true'. Vous pouvez voir les mots-clés enregistrés avec:qui affiche un dictionnaire
Il y a beaucoup d'actions définies, mais un seul type, la valeur par défaut un,
argparse.identity
.Ce code définit un mot clé 'bool':
parser.register()
n'est pas documenté, mais n'est pas non plus caché. Pour la plupart, le programmeur n'a pas besoin de le savoir cartype
ilaction
prend des valeurs de fonction et de classe. Il existe de nombreux exemples de stackoverflow de définition de valeurs personnalisées pour les deux.Dans le cas où cela n'est pas évident à partir de la discussion précédente,
bool()
cela ne signifie pas «analyser une chaîne». Dans la documentation Python:Comparez cela avec
la source
Je cherchais le même problème, et à mon humble avis, la jolie solution est:
et en utilisant cela pour analyser la chaîne en booléen comme suggéré ci-dessus.
la source
distutils.util.strtobool(v)
.distutils.util.strtobool
retourne 1 ou 0, pas un booléen réel.Une manière assez similaire consiste à utiliser:
et si vous définissez l'argument --feature dans votre commande
l'argument sera True, si vous ne définissez pas type --feature les arguments par défaut sont toujours False!
la source
--feature False
En plus de ce que @mgilson a dit, il convient de noter qu'il existe également une
ArgumentParser.add_mutually_exclusive_group(required=False)
méthode qui rendrait l'application de cela triviale--flag
et qui--no-flag
n'est pas utilisée en même temps.la source
Cela fonctionne pour tout ce que j'attends:
Le code:
la source
_str_to_bool(s)
pour convertirs = s.lower()
une fois, puis testerif s not in {'true', 'false', '1', '0'}
et enfinreturn s in {'true', '1'}
.Une manière plus simple serait d'utiliser comme ci-dessous.
la source
Le plus simple. Ce n'est pas flexible, mais je préfère la simplicité.
EDIT: Si vous ne faites pas confiance à l'entrée, ne l'utilisez pas
eval
.la source
eval
est une fonction intégrée. docs.python.org/3/library/functions.html#eval Il peut s'agir de n'importe quelle fonction unaire dont profitent d'autres approches plus flexibles.Le moyen le plus simple serait d'utiliser des choix :
Ne passe pas --my-flag est évalué à False. L' option required = True peut être ajoutée si vous souhaitez toujours que l'utilisateur spécifie explicitement un choix.
la source
Je pense que la manière la plus canonique sera:
la source
la source
La manière la plus simple et la plus correcte est
Notez que les valeurs vraies sont y, oui, t, true, on et 1; les fausses valeurs sont n, non, f, faux, désactivé et 0. Déclenche ValueError si val est autre chose.
la source
Rapide et facile, mais uniquement pour les arguments 0 ou 1:
La sortie sera "False" après avoir appelé depuis le terminal:
la source
Similaire à @Akash mais voici une autre approche que j'ai utilisée. Il utilise
str
quelambda
parce que le pythonlambda
me donne toujours des sentiments extraterrestres.la source
Pour améliorer la réponse de @Akash Desarda, vous pourriez faire
Et il prend en charge
python test.py --foo
la source