2012-03-30 25 views
11

Estoy convirtiendo 2 MB de datos como una cadena en un dict. La entrada se serializa en JSON.python eval vs ast.literal_eval vs JSON decode

De todos modos, actualmente estoy usando ast.literal_eval y obtengo el diccionario que quiero, pero cuando intento ejecutar simplemente eval parece que se ejecuta más rápido, y también devuelve el mismo resultado.

¿Hay alguna razón para usar el módulo ast o el módulo json cuando eval funciona bien?

+0

Si quiere distribuir el diccionario junto con su código, puede simplemente ponerlo en un módulo de Python e importarlo. De esa forma, deja en claro que este es el código de Python. –

Respuesta

17

Sí, definitivamente hay una razón: eval() es malo. Su código podría leer datos no confiables un día, y esto le permitiría a un atacante ejecutar código arbitrario en su máquina.

No debe usar ast.literal_eval() para decodificar JSON tampoco. No puede decodificar todas las cadenas JSON válidas y no está destinado a ser utilizado para este propósito. Simplemente use json.loads(), es bastante rápido.

+1

¿Qué pasa si solo pueden ejecutarlo en su propia máquina? (por ejemplo: lo descargan y lo ejecutan) – MxyL

+2

@Keikoku: Entonces, si no es su máquina, ¿no le importa? –

+0

Supongo que podrían difundirlo y hacer cosas dudosas con él y darme crédito por el trabajo. – MxyL

4

eval es propenso a amenazas de seguridad. Utiliza sólo cuando se controla absolutamente lo que se eval'ed

+0

¿conoce alguna debilidad de seguridad de eval que no se puede solucionar proporcionando ¿Globales? –

16

No. A menos que se golpea uno de los dos escenarios:

  1. Eso no es JSON!

    Alguien pone __import__('os').system('rm -rf /') en el archivo en su lugar. Estás deshuesado.

  2. ¡Es JSON, pero no es la parte de Python!

    Alguien pone true, false, null, o un escape Unicode en algún lugar del mismo. Feliz cumpleaños.

+0

¿Qué tal 'eval (json_str, {'false': False, 'true': True, 'null': None, '__builtins__': {}})'? ;-) –

+3

@NasBanov: ver http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html –

+0

@JanusTroelsen, sí - ver esto http://stackoverflow.com/questions/7282905/does-converting-json-to -dict-with-eval-a-good-choice/7282959 # comment14167166_7282959 - parece relacionado por el tiempo también –

16

que no me gusta mucho esta actitud en StackOverflow (y otras partes) decirle a la gente sin ningún tipo de contexto que lo que están haciendo es insegura y no debería hacerlo. Tal vez es solo un guion desechable para importar algunos datos, en ese caso, ¿por qué no elegir la forma más rápida o más conveniente?

En este caso, sin embargo, json.loads no solo es más seguro, sino también más de 4 veces más rápido (según sus datos).

In [1]: %timeit json.loads(data) 
10000 loops, best of 3: 41.6 µs per loop 

In [2]: %timeit eval(data) 
10000 loops, best of 3: 194 µs per loop 

In [3]: %timeit ast.literal_eval(data) 
1000 loops, best of 3: 269 µs per loop 

Si se piensa en ello hace JSON sentido es un tipo de lenguaje/formato más limitados que pitón, por lo que debe ser más rápido que analizar con un analizador optimizado.

+0

SO es algo más que responder la pregunta del OP: se convierte en una referencia que otras personas leen también. –

0

No es una respuesta exacta, pero debe tenerse en cuenta que eval y literal_eval no son lo mismo. El ast.literal_eval no ejecutará código arbitrario.

Dicho esto, estoy de acuerdo con el uso de JSON; Solo quería señalar que eval != literal_eval