2010-12-08 26 views
11

Estoy haciendo una aplicación web que procesa algunos datos, por lo que con frecuencia me encuentro analizando cadenas (desde una URL o un archivo de texto) a Valores de Python.Python "safe" eval (string to bool/int/float/None/string)

Puedo utilizar una función que es "una especie de" una versión más segura de eval (excepto que si no se puede leer la cadena, se mantiene una cadena):

def str_to_value(string): 
    for atom in (True, False, None): 
     if str(atom) == string: 
      return atom 
    else: 
     try: 
      return int(string) 
     except ValueError: 
      try: 
       return float(string) 
      except ValueError: 
       return string 

... sin embargo, esta me parece muy feo ¿Hay una forma más limpia de hacer esto? Encontré un old discussion os algo como esto, pero me pregunto si no hay una manera rápida y sencilla (como una función de la biblioteca que no conozco, o una ingeniosa línea).

+0

No, creo que si desea permitir que cualquiera de estos tipos esta es probablemente la manera de hacerlo. Pero me parece extraño. ¿No sabes de qué tipo será la entrada? ¿Cómo sabrá qué hacer con la entrada? –

+1

Esto no es seguro a menos que confíes en 'string' para ser un' str' (y no una subclase, tampoco) - de lo contrario, un malvado podría escribir una clase con un método malicioso '__eq__' que se llamaría cuando pruebas si su cadena se ve como True. – katrielalex

+0

Lennart: por ejemplo, puedo usar este tipo de conversión en una función CsvToDict genérica, que luego se usará en ExpectKeysToBeInts (CsvToDict ("ints_as_keys.csv")) y en ExpectValuesToBeFloats (CsvToDict ("float_values.csv")) - Prefiero que mis ExpectKeysToBeInts y ExpectValuesToBeFloats sean simples y no tengan que preocuparse por la conversión de datos. – Emile

Respuesta

27

ast.literal_eval()

>>> ast.literal_eval('{False: (1, 0x2), True: [3.14, 04, 0b101], None: ("6", u"7", r\'8\')}') 
{False: (1, 2), True: [3.1400000000000001, 4, 5], None: ('6', u'7', '8')} 
+1

Gracias! [La máquina del tiempo de Guido] (http://dirtsimple.org/2004/12/python-is-not-java.html) ataca de nuevo. Tendré que buscar en la biblioteca ast, es una de esas bibliotecas de "propósito general" que probablemente contenga cosas útiles (como itertools, functools, colecciones ...) – Emile

+4

Me acabo de dar cuenta de cuántos hackers sucios malvados he creado en el pasado que debería haber estado usando esto en lugar de simplemente 'eval'. Ay. :) –