2013-04-14 8 views
7

NOTA BENE: NON si tratta dell'uso di eval(), si tratta della qualità potenziale (o meno) di un libro in cui viene utilizzato e insegnato. COSÌ ha già innumerevoli discussioni su eval() in Python.Python - Il libro di Zelle usa eval(), è sbagliato?

Rischiando di invitare l'ira ei downvotes di SO, ho comunque deciso di porre questa domanda, per ogni evenienza. Per favore, sopportami. Ho provato Google e SO per questa specifica domanda (come vedrai) e non ho ottenuto nulla. Potrei essere cieco, però.

Questa domanda riguarda l'uso della famigerata funzione eval().

C'è un relativamente ben noto (e ben recensito, come si può vedere) libro di John Zelle: http://www.amazon.com/Python-Programming-Introduction-Computer-Science/dp/1590282418/ref=pd_sim_b_3

Tecnicamente, è un libro CS1 che utilizza Python come linguaggio di programmazione. Abbastanza corretto, questo tipo di responsabilità trae dalle spalle dell'autore ("Ehi, sto cercando di insegnarti qualcosa di ampio qui, non tutti questi dettagli di sintassi e sicurezza"), ma quando ho iniziato a leggerlo ho notato, letteralmente il primo esempio, l'uso di

x = eval(input("Enter your number: "))

dove x deve essere un int e quindi dobbiamo convertire input dell'utente in un int.

Sto usando Python 2.7.4 e il libro parla di Python 3, quindi ho dovuto affrontare un sacco di problemi con print() e input() ed eval() fin dall'inizio e ho dovuto fare qualcosa ricerca per far funzionare gli esempi. Nel corso della mia ricerca, ho letto innumerevoli opinioni su eval() in Python (principalmente qui su SO) che si riducono quasi sempre a un rischio di sicurezza, a un sovraccarico tecnico non necessario e così via. Le domande degli utenti erano molto più elaborate (ce n'era una sull'utilizzo di eval() quando si esegue un progetto wxPython), quindi non posso garantire la totale somiglianza tra il mio caso e i loro casi, ma ...

Quindi, lo ammetto, non sono troppo avanti nel libro, ma ho raggiunto il punto in cui, un po 'più avanti, l'autore ha spiegato l'uso di eval() senza alcun riferimento alla sua natura controversa. Ha praticamente detto quello che ho appena detto: abbiamo bisogno che x diventi un int, quindi ecco un modo pratico per farlo. E sembra che lo stia usando da sempre.

La mia domanda è questa: se, fin dall'inizio, un autore commette un tale errore (o NON è un errore? Potrei mancare qualcosa qui), è un libro che vale la pena imparare? Credo che il signor Zelle sia un grande insegnante di CS, e mostra, ma che lo voglia o no, le persone impareranno comunque Python dal suo libro, oltre agli algoritmi e all'arte della programmazione. Vale quindi la pena di imparare Python da un libro che tace su un problema apparentemente universale nella comunità Python? Non voglio che il signor Zelle sia un hacker di Python e scopra tutti i suoi segreti, ma piccoli dettagli come questi possono creare o distruggere qualcuno che è auto-insegnante/auto-apprendimento. Quale sarà il tuo consiglio riguardo a questo materiale didattico?

P.S. D'altra parte, farmi fare un bel po 'di ricerca e sperimentazione (inconsapevolmente) fin dall'inizio è abbastanza bello :-)

Grazie!

+0

Ho pensato che eval fosse malvagio solo in JavaScript –

+5

@JasonSperske È malvagio ovunque – jamylak

+4

Suggerire eval() invece di int() sembra fuorviato. –

risposta

9

Come autore del libro in questione, lasciatemi ponderare su questo problema.

L'uso di eval nel libro è in gran parte un artefatto storico della conversione da Python 2 a Python 3 (sebbene lo stesso "difetto" esista nell'uso dell'input in Python 2). Sono ben consapevole dei pericoli dell'utilizzo di eval nel codice di produzione in cui l'input può provenire da una fonte non attendibile, ma il libro non riguarda il codice di produzione per un sistema basato sul web; si tratta di imparare alcuni concetti di CS e di programmazione. Non c'è davvero nulla nel libro che possa essere considerato in remoto come codice di produzione. Il mio obiettivo è sempre quello di utilizzare l'approccio più semplice che mi permetta di illustrare il punto che sto cercando di fare, e la valutazione aiuta a farlo.

Non sono d'accordo con la folla che proclama il male in tutti i contesti. È molto utile per programmi e script semplici che vengono eseguiti solo dal loro autore. In quel contesto, è perfettamente sicuro. Permette input ed espressioni multipli semplici come input . Pedagogicamente, enfatizza il concetto di valutazione dell'espressione. Eval espone tutto il potere (e il pericolo) di un linguaggio interpretato. Uso eval tutto il tempo nei miei programmi personali (e non solo in Python). Con il senno di poi, sono assolutamente d'accordo sul fatto che avrei dovuto includere una discussione sui potenziali rischi della valutazione; questo è qualcosa che faccio sempre nelle mie lezioni, comunque.

La linea di fondo è che ci sono molti modi in cui questo libro potrebbe essere migliorato (ci sono sempre). Non penso che l'uso di eval sia un difetto fatale; è appropriato per i tipi di programmi illustrati e il contesto in cui appaiono tali programmi.Non sono a conoscenza di altre "insicurezze" nel modo in cui Python viene usato nel libro, ma dovresti essere avvisato (come spiega la Prefazione) che ci sono numerosi luoghi in cui il codice non è esattamente "Pythonic".

+5

Ti sei appena unito a StackOverflow per rispondere a questo? Wow, bravo con te, onestamente, rispondendo pubblicamente hai incuriosito il tuo libro (sto imparando Python). Sono sempre felice di vedere gli autori di questo sito coinvolgere altri programmatori. Spero che essere parte di questo sito ti renda un autore e un insegnante migliori e con rispetto e sincerità, benvenuti a Stack Overflow :) –

+0

Penso che i migliori libri siano quelli in cui l'autore è accessibile. Quindi, forse, la tua terza aggiunta sarebbe meglio a questo riguardo. Detto questo, non sono d'accordo con te sul fatto che l'uso di eval() sia un problema "pitonico". Credo che sia una questione fondamentale se i lettori del libro impareranno a fare le cose correttamente o no. Sono d'accordo con te sul fatto che dovresti menzionare le vulnerabilità della sicurezza che i tuoi script hanno, o, ancora meglio, scrivere codice Python 3 che non soffre della cronologia della conversione rapida dal codice Python 2. – Kaydell

2

eval deve essere digitato evil invece di avvisare le persone di questo;) Si dovrebbe provare e mai usare a meno che non sia assolutamente necessario. In questo caso è intuitivo usare int() invece, è ancora più leggibile!Inoltre, se davvero dovessi, potresti usare ast.literal_eval (valuta solo i letterali come suggerisce il nome, quindi non permetterà all'utente di eseguire codice dannoso) che è effettivamente sicuro, ma non ce n'è bisogno e non c'è bisogno per eval() in questo caso.

+0

Grazie! La mia domanda, però, era un po 'più sulla tua opinione su un tale codice presente in un libro di CS-Python da un rispettato professore, che i principianti dovrebbero teoricamente fidarsi totalmente. È un brutto libro o è solo un piccolo errore che ha fatto che non dovrebbe dire molto altro sulla qualità del materiale? – Leo

4

Dato che lo eval è così fuori luogo e non necessario nell'esempio che si fornisce, avrei sicuramente dubbi sulla sicurezza di altre parti del libro. L'autore suggerirà di aggiungere una stringa inserita dall'utente a una query SQL?

Penso che valga la pena trovare l'indirizzo e-mail dell'autore e chiederglielo direttamente.

+0

Grazie! Ho preso in considerazione l'idea di farlo ma poi chi diavolo sono io a interrogare un professore di CS? Sono solo un semi-programmatore hobbista con pochissimi progetti alla mia portata. La mia laurea universitaria non ha nulla a che fare con i computer o con qualsiasi tecnologia. È molto più probabile che io sia l'idiota qui e non lui. È solo strano ... Un libro che è usato nelle università, sicuramente qualcuno avrebbe fatto questa domanda ormai, ma Google non dà niente. – Leo

+0

@Gleb - Ma non stai mettendo in discussione l'uso di "eval" puramente basato sulla tua conoscenza. [Non sei da solo su questo] (http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html), quindi vai e chiedi. Che cosa hai da perdere? – root

+1

Ho trovato l'e-mail dell'autore e gli ho chiesto questo. Tutti dicono che è un bravo ragazzo quindi spero che non si arrabbi con me :-) Anche se i principianti non dovrebbero preoccuparsi della sicurezza, è sempre deludente presentare un frammento di codice in qualche posto come questo sito web e affrontare una raffica di. .. beh, non odio, ovviamente, ma una raffica di critiche sulla falsariga di "Chi ti ha insegnato a farlo in questo modo 0_o?!" – Leo

3

Bene, combinare eval() e input() in questo modo crea una "shell" rudimentale ma probabilmente molto dannosa. Non ho letto il libro, ma lo prenderei con un pizzico di sale. Non è solo una cattiva pratica, ma implementa una combinazione di funzioni mortali.

5

Sì, è sbagliato. Ma penso di sapere perché è lì dentro.

Un sacco di persone usano input() in Python 2.x, che è una funzione chiamata molto sfortunatamente dal momento che non legge solo l'input, ma lo valuta anche. Il convertitore 2to3 converte ogni uso di input()-eval(input()), come si può vedere:

$ cat test.py 
x = input("Enter your number: ") 

$ 2to3 test.py 
RefactoringTool: Skipping implicit fixer: buffer 
RefactoringTool: Skipping implicit fixer: idioms 
RefactoringTool: Skipping implicit fixer: set_literal 
RefactoringTool: Skipping implicit fixer: ws_comma 
RefactoringTool: Refactored test.py 
--- test.py  (original) 
+++ test.py  (refactored) 
@@ -1 +1 @@ 
-x = input("Enter your number: ") 
+x = eval(input("Enter your number: ")) 
RefactoringTool: Files that need to be modified: 
RefactoringTool: test.py 

Quindi la mia ipotesi è che è solo un po 'sciatta. Dalla descrizione di Amazon:

Questa è la seconda edizione di programmazione Python di John Zelle, aggiornato per Python 3.

Credo che qualcuno correva 2to3 su tutti gli esempi di codice senza controllare l'uscita abbastanza bene . Quindi sì, è stato un errore usare input() in Python 2.x, ed è stato un errore usare 2to3 senza controllare l'output.

+2

Penso che tu abbia ragione con la tua piccola indagine lì, ma il problema è che l'autore commenta effettivamente l'uso di eval() senza rivelare alcuna delle implicazioni. Se l'unico scopo di questa edizione (come è vagamente indicato nell'introduzione) è Python 3, allora il suo Python 3 dovrebbe essere, beh, valido Python 3, e non solo un aggiornamento cieco. L'intera ragione per creare Python 3 così com'è, è risolvere questo tipo di problemi. Penso che ogni libro dovrebbe tenerne conto. – Leo

+2

Quindi l'errore dell'autore era con la prima edizione quando non utilizzavano raw_input() –