asmeurer
me gustaria usar el ArgumentError
excepción en el argparse
módulo en Python, pero no puedo averiguar cómo usarlo. La firma dice que debería llamarse como ArgumentError(argument, message)
pero no puedo entender qué argument
debiera ser. Creo que debería ser una parte del objeto del analizador, pero no pude encontrar ninguna documentación al respecto.
dar un toque
ArgumentError: la excepción que generan los objetos ArgumentParser cuando hay errores con las acciones del analizador. ArgumentParser detecta los errores generados al analizar la línea de comandos y los emite como mensajes de la línea de comandos.
El argument
El parámetro del constructor es el Action
objeto desde el que se genera la excepción. Por lo general, no hay necesidad de elevarlo fuera de un Action
subclase, y al subclasificarla, no hay necesidad de generarla explícitamente; sueles subir ValueError
(o lo que sea apropiado) en su lugar.
Valores flotantes entre 0 y 1
Con respecto a su comentario, que solo desea aceptar valores de punto flotante entre 0 y 1. Para esto, debe usar la capacidad de definir tipos personalizados. Puedes hacerlo por ejemplo así:
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()
Tenga en cuenta que esto también es seguro contra los no flotantes como float(string)
levantará un ValueError
para no flotantes que también desencadena un error de tipo no válido por el argparse
módulo. ArgumentTypeError
es solo una forma de especificar un mensaje de error personalizado.
Parámetros mutuamente excluyentes
Para parámetros mutuamente excluyentes, debe usar argparse.add_mutually_exclusive_group
.
Dependencia de parámetros
La dependencia de parámetros no es realmente algo que deba hacer el argumento analizador. Para obtener detalles semánticos, simplemente debe hacerlo usted mismo:
args = parser.parse_args()
if args.w and not args.p:
parser.error('-p is required when -w is set.')
Puedes usar ArgumentParser.error
para generar un mensaje de error personalizado que interrumpirá el programa e imprimirá en la consola.
Pero, por supuesto, en una situación tan básica tendría mucho más sentido simplemente adivinar implícitamente -p
si es posible.
-
Eso no está bien. Si solo envío el valor, obtengo
AttributeError: 'float' object has no attribute 'option_strings'
.– Asmeurer
12 de noviembre de 2011 a las 23:03
-
Y, por cierto, quiero usarlo porque quiero hacer una verificación de tipo que el módulo no admita directamente. Por ejemplo, quiero un valor de punto flotante que esté entre 0 y 1. argparse le permite especificar que debería ser un valor flotante, pero tengo que verificar manualmente el rango. Este parece ser el error correcto para emitir cuando el valor es incorrecto.
– Asmeurer
12 de noviembre de 2011 a las 23:04
-
@asmeurer Edité mi respuesta para darle un ejemplo de cómo hacerlo.
– dar un toque
12 de noviembre de 2011 a las 23:37
-
El voto negativo es porque la respuesta es incorrecta. ArgumentError (1.1, “Valor fuera de rango”) genera AttributeError, como mencioné anteriormente. Esto debe ser algún tipo de objeto argparse interno, pero no puedo entender qué. Y, por cierto, otro ejemplo de cuándo puede querer hacer esto es cuando quiere definir una dependencia no trivial de los argumentos, que por lo que sé, el módulo argparse no admite directamente. Algo como el
-w
opción requiere la-p
opción, o-n
y-N
son mutuamente excluyentes.– Asmeurer
13 de noviembre de 2011 a las 20:56
ukrutt
Mientras parser.error()
es lo que la mayoría de la gente probablemente quiera, también es posible usar argparse.ArgumentError() (como hace la pregunta). Necesita una referencia al argumento, como el bar_arg
en el siguiente ejemplo:
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'")
Esto dará como resultado una salida como la siguiente:
$ 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 <module>
raise argparse.ArgumentError(bar_arg, "Can't be 'xyzzy'")
argparse.ArgumentError: argument --bar: Can't be 'xyzzy'
-
Este es un buen ejemplo de cómo usar
ArgumentError
fuera de laparser
es posible, pero probablemente inferior a usarparser.error
.– hpaulj
12 de marzo de 2015 a las 19:03
-
@hpaulj, sí, pero ArgumentError tiene un beneficio: le permite saber qué interruptor fue el infractor.
– ukrutt
13 de marzo de 2015 a las 11:42
-
Bueno, si escribes bien tu mensaje de error, entonces te asegurarás de mencionar qué interruptor era el ofensivo. Crear una variable separada para cada argumento agregado puede ser muy engorroso…
– Praveen
14/09/2016 a las 22:55
-
@Praveen Supongo que es una cuestión de preferencia. Yo mismo prefiero la variable a escribir “‘–foo’ no puede ser ‘xyzzy'”, ya que luego tengo que recordar cuál era el nombre propio del interruptor (no es necesariamente el mismo que el atributo a
args
). Pero honestamente, creoparser.error()
debe incluir el nombre del conmutador infractor de forma predeterminada.– ukrutt
16/09/2016 a las 16:23
-
Puedes usar
args.bar
como el argumento deArgumentError
no solobar_arg
.– Yaroslav Nikitenko
3 de febrero de 2021 a las 11:56
Relacionado: ¿Es de mala forma criar?
ArgumentError
¿manualmente?– DavidRR
12/03/2015 a las 12:50
Puedes usarlo dentro de una costumbre
Action
clase, tal como lo hacen las clases existentes. Pero no puedo imaginar una razón para hacerlo fuera de laparser
. No tiene nada especial, solo agrega elAction
nombre al mensaje de error. Estudiar su uso en el código.– hpaulj
12 de marzo de 2015 a las 17:08