2009-07-05 8 views
20

Las mejores prácticas a un lado, ¿hay una razón de peso no para hacer esto?Ejecutando JSON a través de la evaluación de Python()?

Estoy escribiendo un enganche post-commit para usar con un proyecto de Google Code, que proporciona datos de confirmación a través de un objeto JSON. GC proporciona un token de autenticación HMAC junto con la solicitud (fuera de los datos JSON), por lo que al validar ese token obtengo una gran confianza en que los datos JSON son a la vez benignos (ya que no tiene sentido desconfiar de Google) y son válidos.

Mis propias (breves) investigaciones sugieren que JSON pasa a ser completamente válido Python, con la excepción de la secuencia de escape "\/", que GC no parece generar.

Así que, como estoy trabajando con Python 2.4 (es decir, no hay ningún módulo json), eval() está buscando realmente tentador.

Editar: Para que conste, yo soy mucho no preguntando si esto es una buena idea. Estoy bastante consciente de que no lo es, y dudo mucho que alguna vez use esta técnica para proyectos futuros, incluso si termino usándolo para este. Solo quería asegurarme de saber con qué tipo de problemas me encontraré si lo hago. :-)

Respuesta

28

Si te sientes cómodo con tu script y funciona bien por un tiempo, y luego falla aleatoriamente en algún caso oscuro, iré con eval.

Si es importante que su código sea robusto, me tomaría el tiempo para agregar simplejson. No necesita la parte C para las aceleraciones, por lo que realmente no debería ser difícil volcar algunos archivos .py en un directorio en algún lugar.

Como un ejemplo de algo que podría morder, JSON utiliza Unicode y simplejson devuelve Unicode, mientras que los rendimientos eval str:

>>> simplejson.loads('{"a":1, "b":2}') 
{u'a': 1, u'b': 2} 
>>> eval('{"a":1, "b":2}') 
{'a': 1, 'b': 2} 

Editar: un mejor ejemplo de que eval() se comporta de manera diferente:

>>> simplejson.loads('{"X": "\uabcd"}') 
{u'X': u'\uabcd'} 
>>> eval('{"X": "\uabcd"}') 
{'X': '\\uabcd'} 
>>> simplejson.loads('{"X": "\uabcd"}') == eval('{"X": "\uabcd"}') 
False 

Editar 2: vio otro problema hoy señalado por SilentGhost: eval no maneja true -> True, false -> False, null -> None correctamente.

>>> simplejson.loads('[false, true, null]') 
[False, True, None] 
>>> eval('[false, true, null]') 
Traceback (most recent call last): 
    File "<interactive input>", line 1, in <module> 
    File "<string>", line 1, in <module> 
NameError: name 'false' is not defined 
>>> 
+4

+1 por "falla en un caso de borde oscuro ". Usted también hace un buen punto acerca de Unicode. Estoy bastante seguro de que no es relevante para mi caso de uso particular, pero eso es algo que no había considerado antes. –

+1

Interesante; Podría haber jurado que probé códigos de escape \ uXXXX y los hice funcionar. Probándolos ahora, fallan tal como se muestra aquí. Debo haber estado alucinando. ^.^ –

+1

también si usa las aceleraciones C, entonces simplejson puede devolver una combinación de cadena y unicode, que parece que no tiene interés en solucionarlo - http://code.google.com/p/simplejson/issues/detail? id = 40 –

11

El objetivo de las mejores prácticas es que, en la mayoría de los casos, es una mala idea no tenerlas en cuenta. Si yo fuera tú, usaría un analizador para analizar JSON en Python. Pruebe simplejson, fue muy sencillo para analizar JSON la última vez que lo intenté y dice ser compatible con Python 2.4.

No estoy de acuerdo con que tenga poco sentido desconfiar de Google. No desconfiaría de ellos, pero verificaría la información que obtienes de ellos. La razón por la que me había hecho uso un analizador JSON es justo en su pregunta:

Mis propios (breves) investigaciones sugieren que JSON pasa a ser completamente válido Python, con la excepción de la secuencia "/" escapar - qué GC no parece generar

¿Qué te hace pensar que Google Code nunca generará una secuencia de escape como esa?

El análisis es un problema resuelto si utiliza las herramientas adecuadas. Si intenta tomar atajos de esta manera, eventualmente será mordido por suposiciones incorrectas, o hará algo así como tratar de hackear un analizador sintáctico con la lógica de expresiones regulares y booleanas cuando ya exista un analizador para su idioma de elección.

+0

Si no estuviese ejecutándose en un entorno alojado, probablemente * estaría * usando simplejson. Desafortunadamente, no tengo mucho control sobre mi entorno de Python y sospecho que resolver cómo agregar paquetes personalizados llevará más tiempo que escribir el script real; estamos hablando de 50 líneas, máximas. Del mismo modo, * no * sé que GC no comenzará a generar esa secuencia de escape, pero si lo hace, el guion fallará naturalmente, será obvio que está roto y la solución es fácil. –

+0

Si la solución es fácil, ¿por qué no hacerlo primero de manera fija? –

+0

Porque implica usar una expresión regular para contar barras diagonales inversas. En este momento, no hay expresiones regulares en el guión, y lo dejaré de esa manera si puedo. :-) –

-1

eval ing JSON es un poco como tratar de ejecutar XML a través de un compilador de C++.

eval está destinado a evaluar el código de Python. Aunque hay algunas similitudes sintácticas, JSON no es el código de Python. Diablos, no solo no es Python código, no es un código para empezar. Por lo tanto, incluso si puede salirse con la suya para su caso de uso, yo diría que es una mala idea conceptualmente. Python es una manzana, JSON es refresco con sabor a naranja.

+10

Usted acaba de hacerme querer ejecutar XML a través de un compilador de C++ y ver si puedo conseguir que se compile. Oh plantillas. – Kiv

+2

Heh ... Me pregunto si hay una manera? 'sería interesante. –

2

Una diferencia importante es que un booleano en JSON es true | false, pero Python usa True | False.

La razón más importante para no hacer esto puede generalizarse: eval nunca debe utilizarse para interpretar entradas externas, ya que esto permite la ejecución de código arbitrario.

Cuestiones relacionadas