the parser following example error argumentparser argument arg_parser are add_argument python argparse negative-number

parser - python argparse optional



Python Argparse: Problema con argumentos opcionales que son nĂºmeros negativos (7)

Estoy teniendo un pequeño problema con argparse . Tengo una opción xlim que es el xrange de una parcela. Quiero poder pasar números como -2e-5 . Sin embargo, esto no funciona; argparse interpreta que este es un argumento posicional. Si hago -0.00002 funciona: argparse lee como un número negativo. ¿Es posible tener lectura en -2e-3 ?

El código está abajo, y un ejemplo de cómo lo ejecutaría es:

./blaa.py --xlim -2.e-3 1e4

Si hago lo siguiente funciona:

./blaa.py --xlim -0.002 1e4

El código:

parser.add_argument(''--xlim'', nargs = 2, help = ''X axis limits'', action = ''store'', type = float, default = [-1.e-3, 1.e-3])

Si bien puedo hacerlo funcionar de esta manera, realmente preferiría poder usar la notación científica. ¿Alguien tiene alguna idea?

Aclamaciones


Aquí está el código que utilizo. (Es similar a la de jeremiahbuddha, pero responde a la pregunta más directamente ya que trata con números negativos).

Coloca esto antes de llamar a argparse.ArgumentParser()

for i, arg in enumerate(sys.argv): if (arg[0] == ''-'') and arg[1].isdigit(): sys.argv[i] = '' '' + arg


Como ya se señaló en los comentarios, el problema es que un prefijo se analiza como una opción en lugar de como un argumento. Una forma de solucionar esto es cambiar el prefijo utilizado para las opciones con el argumento prefix_chars :

#!/usr/bin/python import argparse parser = argparse.ArgumentParser(prefix_chars=''@'') parser.add_argument(''@@xlim'', nargs = 2, help = ''X axis limits'', action = ''store'', type = float, default = [-1.e-3, 1.e-3]) print parser.parse_args()

Ejemplo de salida:

$ ./blaa.py @@xlim -2.e-3 1e4 Namespace(xlim=[-0.002, 10000.0])

Edición: Alternativamente, puede seguir usando - como separador, pasar xlim como un solo valor y usar una función de type para implementar su propio análisis:

#!/usr/bin/python import argparse def two_floats(value): values = value.split() if len(values) != 2: raise argparse.ArgumentError values = map(float, values) return values parser = argparse.ArgumentParser() parser.add_argument(''--xlim'', help = ''X axis limits'', action = ''store'', type=two_floats, default = [-1.e-3, 1.e-3]) print parser.parse_args()

Ejemplo de salida:

$ ./blaa.py --xlim "-2e-3 1e4" Namespace(xlim=[-0.002, 10000.0])


Inspirado por el enfoque de andrewfn, creé una función de ayuda separada para hacer el violín de sys.argv :

def _tweak_neg_scinot(): import re import sys p = re.compile(''-//d*//.?//d*e'', re.I) sys.argv = ['' '' + a if p.match(a) else a for a in sys.argv]

El regex busca:

  • - : un signo negativo
  • //d* : cero o más dígitos (para valores con formato extraño como -.5e-2 o -4354.5e-6 )
  • //.? : un período opcional (por ejemplo, -2e-5 es razonable)
  • //d* : otro conjunto de cero o más dígitos (para cosas como -2e-5 y -7.e-3 )
  • e : para hacer coincidir el marcador de exponente

re.I hace que coincida con -2e-5 y -2E-5 . Usar p.match significa que solo busca desde el inicio de cada cadena.


Otra solución es pasar el argumento usando el símbolo '' = '' además de citar el argumento, es decir, --xlim="-2.3e14"


Si especifica el valor de su opción con un signo igual, argparse no lo tratará como una opción separada, incluso si comienza con - :

./blaa.py --xlim=''-0.002 1e4'' # As opposed to --xlim ''-0.002 1e4''

Y si el valor no tiene espacios, puede eliminar las comillas:

./blaa.py --xlim=-0.002

Consulte: https://www.gnu.org/software/guile/manual/html_node/Command-Line-Format.html

Con esto, no es necesario escribir su propio type= analizador o redefinir el carácter de prefijo de - a @ como sugiere la respuesta aceptada.


Si está modificando el propio argparse.py , podría cambiar el emparejador de números negativos para manejar la notación científica:

En la class _ActionsContainer.__init__()

self._negative_number_matcher = _re.compile(r''^-(/d+/.?|/d*/./d+)([eE][+/-]?/d+)?$'')

O después de crear el analizador, puede establecer parser._negative_number_matcher en este valor. Este enfoque podría tener problemas si está creando grupos o subparsers, pero debería funcionar con un analizador simple.


Una solución que he encontrado es citar el valor, pero agregar un espacio. Es decir,

./blaa.py --xlim " -2.e-3" 1e4

De esta manera, argparse no pensará que -2.e-3 es un nombre de opción porque el primer carácter no es un guión con guión, pero aún se convertirá correctamente en un flotador porque flotante (cadena) ignora los espacios de la izquierda.