Me gustaría utilizar argparse para analizar argumentos de línea de comandos booleanos escritos como "--foo True" o "--foo False". Por ejemplo:
my_program --my_boolean_flag False
Sin embargo, el siguiente código de prueba no hace lo que me gustaría:
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)
Tristemente, parsed_args.my_bool
evalúa a True
. Este es el caso incluso cuando cambio cmd_line
a ser ["--my_bool", ""]
, lo cual es sorprendente, ya que bool("")
evalúa False
.
¿Cómo puedo obtener argparse a analizar "False"
, "F"
y su minúscula variantes que se vayan False
?
python
boolean
argparse
command-line-parsing
Súper eléctrico
fuente
fuente
parser.add_argument('--feature', dest='feature', default=False, action='store_true')
. Esta solución le garantizará que siempre obtenga unbool
tipo con valorTrue
oFalse
. (Esta solución tiene una restricción: su opción debe tener un valor predeterminado).parser.add_argument('--feature', dest='feature', type=lambda x:bool(distutils.util.strtobool(x)))
. Cuando se utiliza la opción, esta solución garantizará unbool
tipo con valor deTrue
oFalse
. Cuando no se utiliza la opción, obtendráNone
. (distutils.util.strtobool(x)
es de otra pregunta de stackoverflow )parser.add_argument('--my_bool', action='store_true', default=False)
Respuestas:
Otra solución más usando las sugerencias anteriores, pero con el error de análisis "correcto" de
argparse
:Esto es muy útil para hacer cambios con valores predeterminados; por ejemplo
me permite usar:
y aún usa un valor predeterminado (específico para la configuración del usuario). Una desventaja (indirectamente relacionada) con ese enfoque es que los 'nargs' pueden atrapar un argumento posicional: vea esta pregunta relacionada y este informe de error de argparse .
fuente
str2bool(v)
podría ser reemplazado porbool(distutils.util.strtobool(v))
. Fuente: stackoverflow.com/a/18472142/2436175if args.nice:
porque si el argumento está configurado como False, nunca pasará la condición. Si esto es correcto, entonces quizás es mejor a la lista de volver destr2bool
la función y la lista de canciones comoconst
parámetro, como este[True]
,[False]
.Creo que una forma más canónica de hacer esto es a través de:
y
argparse
admite esta versión muy bien:Por supuesto, si realmente quieres la
--arg <True|False>
versión, puedes pasarlaast.literal_eval
como "tipo" o como una función definida por el usuario ...fuente
type=bool
debería funcionar fuera de la caja (¡considere los argumentos posicionales!) Incluso cuando especificas adicionalmentechoices=[False,True]
, terminas con "Falso" y "Verdadero" considerado Verdadero (¿debido a un lanzamiento de cadena a bool?). Tal vez un problema relacionadobool()
debería hacer la función Python , o qué argumento debería aceptartype=fn
? Todos losargparse
chequesfn
son invocables. Esperafn
tomar un argumento de cadena y devolver un valor. El comportamiento defn
es responsabilidad del programador, noargparse's
.Recomiendo la respuesta de mgilson pero con un grupo mutuamente excluyente
para que no pueda usar
--feature
y--no-feature
al mismo tiempo.y
pero no
Guión:
Luego puede usar este asistente si va a configurar muchos de ellos:
fuente
add_argument
se llama condest='feature'
.set_defaults
se llama confeature=True
. ¿Entender?--flag False
, parte de las respuestas de SO deberían ser sobre QUÉ están tratando de resolver, no solo sobre CÓMO. No debería haber absolutamente ninguna razón para hacer--flag False
o--other-flag True
usar un analizador personalizado para convertir la cadena a booleana ...action='store_true'
yaction='store_false'
son las mejores formas de usar banderas booleanas... can be “don’t do that”, but it should also include “try this instead”
que (al menos para mí) implica respuestas debe profundizar cuando sea apropiado. Definitivamente, hay momentos en que algunos de nosotros que publicamos preguntas pueden beneficiarnos de la orientación sobre mejores / mejores prácticas, etc. Responder "como se dice" a menudo no hace eso. Dicho esto, su frustración con las respuestas a menudo suponiendo demasiado (o incorrectamente) es completamente válida.parser.set_defaults(feature=None)
help=
entrada para este argumento, ¿a dónde debería ir? En laadd_mutually_exclusive_group()
llamada? ¿En una o ambasadd_argument()
llamadas? ¿En algún otro lugar?Aquí hay otra variación sin fila / s extra para establecer valores predeterminados. El bool siempre tiene un valor asignado para que pueda usarse en declaraciones lógicas sin comprobaciones previas.
fuente
required=True
o de lo contrario siempre obtendrás un argumento verdadero.python3 test.py --do-something False
fallaerror: unrecognized arguments: False
, por lo que realmente no responde la pregunta.un trazador de líneas:
fuente
type=lambda x: (str(x).lower() in ['true','1', 'yes'])
Parece haber cierta confusión en cuanto a qué
type=bool
ytype='bool'
podría significar. ¿Debería uno (o ambos) significar 'ejecutar la funciónbool()
o' devolver un booleano '? Tal como estátype='bool'
, no significa nada.add_argument
da un'bool' is not callable
error, igual que si usaratype='foobar'
, otype='int'
.Pero
argparse
tiene un registro que le permite definir palabras clave como esta. Se utiliza principalmente paraaction
, por ejemplo, `action = 'store_true'. Puede ver las palabras clave registradas con:que muestra un diccionario
Hay muchas acciones definidas, pero solo un tipo, el predeterminado,
argparse.identity
.Este código define una palabra clave 'bool':
parser.register()
no está documentado, pero tampoco está oculto. En su mayor parte el programador no necesita saber al respecto porquetype
yaction
valores de la función toma y de clase. Hay muchos ejemplos de stackoverflow para definir valores personalizados para ambos.En caso de que no sea obvio de la discusión anterior,
bool()
no significa 'analizar una cadena'. De la documentación de Python:Contrasta esto con
fuente
Estaba buscando el mismo problema, y en mi humilde opinión, la bonita solución es:
y usar eso para analizar la cadena a booleano como se sugirió anteriormente.
fuente
distutils.util.strtobool(v)
.distutils.util.strtobool
rendimientos de 1 o 0, no un booleano real.Una forma bastante similar es usar:
y si establece el argumento --característica en su comando
el argumento será Verdadero, si no establece el tipo --característica, el argumento predeterminado siempre es Falso!
fuente
--feature False
Además de lo que dijo @mgilson, debe tenerse en cuenta que también hay un
ArgumentParser.add_mutually_exclusive_group(required=False)
método que haría que sea trivial hacer cumplir eso--flag
y que--no-flag
no se usen al mismo tiempo.fuente
Esto funciona para todo lo que espero:
El código:
fuente
_str_to_bool(s)
para convertirs = s.lower()
una vez, luego probarif s not in {'true', 'false', '1', '0'}
y finalmentereturn s in {'true', '1'}
.Una forma más sencilla sería usar la siguiente.
fuente
Más simple No es flexible, pero prefiero la simplicidad.
EDITAR: si no confía en la entrada, no la use
eval
.fuente
eval
Es una función incorporada. docs.python.org/3/library/functions.html#eval Esta puede ser cualquier función unaria que aprovechan otros enfoques más flexibles.La forma más sencilla sería usar opciones :
No pasa --mi-flag se evalúa como False. La opción required = True podría agregarse si siempre desea que el usuario especifique explícitamente una opción.
fuente
Creo que la forma más canónica será:
fuente
fuente
La forma más simple y correcta es
Tenga en cuenta que los valores verdaderos son y, yes, t, true, on y 1; los valores falsos son n, no, f, falso, apagado y 0. Aumenta ValueError si val es otra cosa.
fuente
Rápido y fácil, pero solo para los argumentos 0 o 1:
El resultado será "Falso" después de llamar desde la terminal:
fuente
Similar a @Akash pero aquí hay otro enfoque que he usado. Utiliza
str
quelambda
debido pitónlambda
siempre me da un extranjero sentimientos.fuente
Como una mejora a la respuesta de @Akash Desarda, podrías hacer
Y es compatible
python test.py --foo
fuente