2009-07-05 13 views
20

Le migliori pratiche a parte, c'è un motivo valido non per fare questo?Esecuzione di JSON tramite eval() di Python?

Sto scrivendo un hook post-commit da utilizzare con un progetto Google Code, che fornisce dati di commit tramite un oggetto JSON. GC fornisce un token di autenticazione HMAC insieme alla richiesta (al di fuori dei dati JSON), quindi, convalidando quel token, acquisisco un'alta confidenza sul fatto che i dati JSON siano sia benigni (dato che c'è poco da sfidare Google) e validi.

Le mie (brevi) indagini suggeriscono che JSON sembra essere Python completamente valido, con l'eccezione della sequenza di escape "\/" - che GC non sembra generare.

Così, come sto lavorando con Python 2.4 (vale a dire nessun modulo json), eval() sta cercando davvero allettante.

Edit: Per la cronaca, io sono molto non chiedendo se questa è una buona idea. Sono piuttosto consapevole che non lo è, e dubito fortemente che userò mai questa tecnica per qualsiasi progetto futuro, anche se finisco per usarlo per questo. Volevo solo essere sicuro di sapere che tipo di problemi avrei incontrato se lo facessi. :-)

risposta

28

Se sei a tuo agio con il tuo script che funziona bene per un po ', e poi casualmente fallendo su qualche caso oscuro, vorrei andare con eval.

Se è importante che il codice sia robusto, mi piacerebbe aggiungere del semplice json. Non hai bisogno della porzione C per gli aumenti di velocità, quindi non dovrebbe essere difficile scaricare alcuni file .py in una directory da qualche parte.

Come esempio di qualcosa che potrebbe mordere, JSON utilizza Unicode e simplejson restituisce Unicode, mentre i rendimenti eval str:

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

Edit: un esempio migliore di dove eval() comporta in modo diverso:

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

Modifica 2: ha visto ancora un altro problema segnalato da SilentGhost: eval non gestisce true -> True, false -> False, null -> Nessuno correttamente.

>>> 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 per "malfunzionamento" qualche oscuro caso limite ". Anche tu fai un buon punto su Unicode. Sono abbastanza sicuro che non sia rilevante per il mio particolare caso d'uso, ma è qualcosa che non avevo considerato prima. –

+1

Interessante; Avrei giurato di aver provato \ uXXXX codici di escape e di averli fatti funzionare. Provale ora, falliscono proprio come tu mostri qui. Devo essere stato allucinato. ^.^ –

+1

anche se usi gli speedups C, allora simplejson può restituire un mix di string e unicode, che sembra non avere interesse nel correggere - http://code.google.com/p/simplejson/issues/detail? id = 40 –

11

Il punto delle migliori pratiche è che nella maggior parte dei casi è una cattiva idea ignorarle. Se fossi in te, userei un parser per analizzare JSON in Python. Prova simplejson, è stato molto semplice per l'analisi di JSON quando l'ho provato l'ultima volta e dichiara di essere compatibile con Python 2.4.

Non sono d'accordo sul fatto che non ci sia motivo di diffidare di Google. Non mi farei diffidare di loro, ma verificherei i dati che ottieni da loro. La ragione per cui mi piacerebbe in realtà uso un parser JSON è giusto nella vostra domanda:

mio (brevi) indagini suggeriscono che JSON sembra essere completamente valida Python, con l'eccezione della sequenza "/" fuga - quale GC non sembra generare.

Cosa ti fa pensare che Google Code non genererà mai una sequenza di escape come quella?

L'analisi è un problema risolto se si utilizzano gli strumenti giusti. Se provi a prendere scorciatoie come questo, alla fine verrai morso da assunzioni errate, o farai qualcosa come tentare di hackerare un parser con regex e logica booleana quando esiste già un parser per la tua lingua preferita.

+0

Se non fossi in esecuzione in un ambiente ospitato, probabilmente * userei * simplejson. Sfortunatamente, non ho molto controllo sul mio ambiente Python e ho il sospetto che lavorare su come aggiungere pacchetti personalizzati richieda più tempo rispetto alla scrittura dello script vero e proprio; stiamo parlando di 50 linee, cima. Allo stesso modo, * non * so che GC non inizierà a generare quella sequenza di escape, ma se lo fa, lo script fallirà naturalmente in modo sicuro, sarà ovvio che è rotto e la correzione è facile. –

+0

Se la correzione è semplice, perché non farlo prima in modo fisso? –

+0

Perché implica l'uso di un'espressione regolare per contare i backslash. Al momento, non ci sono espressioni regex nella sceneggiatura, e lascerò che sia così, se posso. :-) –

-1

eval ing JSON è un po 'come cercare di eseguire XML tramite un compilatore C++.

eval ha lo scopo di valutare il codice Python. Sebbene vi siano alcune somiglianze sintattiche, JSON non è il codice Python. Diamine, non solo non è Python codice, non è il codice per cominciare. Pertanto, anche se puoi farla franca per il tuo caso d'uso, direi che è una cattiva idea concettualmente. Python è una mela, JSON è una soda all'arancia.

+10

Mi hai appena fatto venire voglia di eseguire XML attraverso un compilatore C++ e vedere se riesco a farlo compilare. Oh modelli. – Kiv

+2

Heh ... mi chiedo se c'è un modo? 'potrebbe essere interessante. –

2

Una differenza importante è che un booleano in JSON è true | false, ma Python utilizza True | False.

Il motivo più importante per non farlo può essere generalizzato: eval non deve mai essere utilizzato per interpretare input esterni poiché ciò consente l'esecuzione di codice arbitrario.