2012-03-30 18 views
11

Sto convertendo 2 MB di dati come stringa in un dett. L'input è serializzato in JSON.python eval vs ast.literal_eval vs JSON decode

ogni modo Attualmente sto usando ast.literal_eval e ottengo il dizionario che voglio, ma poi quando ho provato solo in esecuzione eval sembra di correre più veloce, e restituisce anche lo stesso risultato.

C'è qualche ragione per usare il modulo ast o il modulo json quando eval funziona bene?

+0

Se si desidera distribuire il dizionario insieme al proprio codice, è possibile semplicemente inserirlo in un modulo Python e importarlo. In questo modo, chiarisci che questo è il codice Python. –

risposta

17

Sì, c'è sicuramente un motivo: eval() è il male. Il tuo codice potrebbe leggere dati non attendibili un giorno, questo consentirebbe a un utente malintenzionato di eseguire codice arbitrario sulla tua macchina.

Non si deve utilizzare ast.literal_eval() per decodificare JSON. Non può decodificare ogni stringa JSON valida e non è pensata per essere utilizzata a questo scopo. Basta usare json.loads(), è ragionevolmente veloce.

+1

Cosa succede se riescono a eseguirlo solo sulla propria macchina? (ad esempio: lo scaricano e lo eseguono) – MxyL

+2

@Keikoku: Quindi se non è la tua macchina, non ti interessa? –

+0

Immagino che potrebbero diffonderlo e fare cose dubbie con esso e accreditarmi per il lavoro. – MxyL

4

eval è soggetto a minacce alla sicurezza. Uso solo quando è assolutamente controllare ciò che viene eval'ed

+0

conosci qualche debolezza di sicurezza di eval che non può essere risolta fornendo globali? –

16

No. A meno che non si colpisce uno dei due scenari:

  1. Questo non è JSON!

    Nel file viene invece inserito __import__('os').system('rm -rf /'). Sei disossato.

  2. È JSON, ma non la parte simile a Python!

    Qualcuno mette true, false, null o un escape Unicode da qualche parte. Buon compleanno.

+0

Che ne dici di 'eval (json_str, {'false': False, 'true': True, 'null': None, '__builtins__': {}})'? ;-) –

+3

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

+0

@JanusTroelsen, sì - vedere questo http://stackoverflow.com/questions/7282905/does-converting-json-to -dict-with-eval-a-good-choice/7282959 # comment14167166_7282959 - sembra correlato dal tempo anche –

16

non mi piace molto questo atteggiamento su StackOverflow (e altrove) dire alla gente senza alcun contesto che quello che stanno facendo è insicuro e non dovrebbero farlo. Forse è solo uno script usa e getta per importare alcuni dati, in tal caso perché non scegliere il modo più veloce o più conveniente?

In questo caso, tuttavia, json.loads non è solo più sicuro, ma anche più veloce di 4x (a seconda dei dati).

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 

Se ci pensate un senso JSON è un tale linguaggio/formato più limitato di pitone, quindi deve essere più veloce per analizzare con un parser ottimizzato.

+0

SO è più che rispondere alla domanda dell'OP: diventa un riferimento che anche altre persone leggono. –

0

Non è una risposta esatta, ma va notato che eval e literal_eval non sono la stessa cosa. ast.literal_eval non eseguirà codice arbitrario.

Detto questo, sono d'accordo con l'utilizzo di JSON; Volevo solo sottolineare che eval != literal_eval