Usando ‘argparse.ArgumentError’ en Python

5 minutos de lectura

avatar de usuario de asmeurer
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.

  • 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 la parser. No tiene nada especial, solo agrega el Action nombre al mensaje de error. Estudiar su uso en el código.

    – hpaulj

    12 de marzo de 2015 a las 17:08


avatar de usuario de poke
dar un toque

De la documentación fuente:

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

avatar de usuario de ukrutt
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 la parser es posible, pero probablemente inferior a usar parser.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, creo parser.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 de ArgumentErrorno solo bar_arg.

    – Yaroslav Nikitenko

    3 de febrero de 2021 a las 11:56

¿Ha sido útil esta solución?