2012-03-30 6 views
11

Je convertis 2 Mo de données sous forme de chaîne en dict. L'entrée est sérialisée dans JSON.python eval vs ast.literal_eval vs JSON decode

De toute façon j'utilise actuellement ast.literal_eval et j'obtiens le dictionnaire que je veux, mais quand j'essaye juste de courir eval il semble courir plus vite, et retourne également le même résultat.

Y a-t-il une raison d'utiliser le module ast ou le module json quand eval fonctionne très bien?

+0

Si vous voulez distribuer le dictionnaire avec votre code, vous pouvez simplement le mettre dans un module Python et l'importer. De cette façon, vous clarifiez que c'est du code Python. –

Répondre

17

Oui, il y a certainement une raison: eval() est diabolique. Votre code pourrait lire des données non fiables un jour, ce qui permettrait à un attaquant d'exécuter du code arbitraire sur votre machine.

Vous ne devez pas non plus utiliser ast.literal_eval() pour décoder JSON. Il ne peut pas décoder toutes les chaînes JSON valides et n'est pas destiné à être utilisé à cette fin. Il suffit d'utiliser json.loads(), c'est raisonnablement rapide.

+1

Et s'ils ne peuvent l'exécuter que sur leur propre machine? (Par exemple: ils le téléchargent et l'exécutent) – MxyL

+2

@Keikoku: Donc, si ce n'est pas votre machine, vous vous en fichez? –

+0

Je suppose qu'ils pourraient l'étendre et faire des choses douteuses avec elle et créditez-moi pour le travail. – MxyL

4

eval est vulnérable aux menaces de sécurité. A utiliser uniquement lorsque vous contrôlez absolument ce qui sera eval'ed

+0

connaissez-vous une faille de sécurité d'eval qui ne peut être corrigée? globals? –

16

Non Sauf si vous touchez l'un des deux scénarios:

  1. Ce n'est pas JSON!

    Quelqu'un met __import__('os').system('rm -rf /') dans le fichier à la place. Tu es désossé.

  2. C'est JSON, mais pas la partie semblable à Python!

    Quelqu'un met true, false, null, ou Unicode échapper quelque part en elle. Bon anniversaire.

+0

'eval (json_str, {'faux': faux, 'vrai': vrai, 'null': aucun, '__builtins__': {}})'? ;-) –

+3

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

+0

@JanusTroelsen, ouais - voir ceci http://stackoverflow.com/questions/7282905/does-converting-json-to -dict-avec-eval-un-bon choix/7282959 # comment14167166_7282959 - semble lié par le temps aussi –

16

Je ne aime pas vraiment cette attitude sur stackoverflow (et ailleurs) de dire aux gens sans contexte que ce qu'ils font est précaire et ils ne devraient pas le faire. Peut-être que c'est juste un script jetable pour importer des données, dans ce cas, pourquoi ne pas choisir le moyen le plus rapide ou le plus pratique?

Dans ce cas, cependant, json.loads est non seulement plus sécurisé, mais aussi plus de 4x plus rapide (selon vos données).

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 vous pensez qu'il est logique JSON est un langage/format plus contraignant que python, donc il doit être plus rapide pour analyser avec un analyseur optimisé.

+0

SO est à peu près plus que de répondre à la question de l'OP: elle devient une référence que d'autres personnes lisent aussi. –

0

Pas exactement une réponse, mais il est à noter que eval et literal_eval ne sont pas la même chose. Le ast.literal_eval n'exécutera pas de code arbitraire.

Cela dit, je suis d'accord avec l'utilisation de JSON; Je voulais simplement faire remarquer que eval != literal_eval