2013-04-14 15 views
7

PROSZĘ ZWRÓCIĆ UWAGĘ: NIE dotyczy to użycia eval(), dotyczy to potencjalnej jakości (lub jej braku) książki, z której jest ona używana i której się uczy. SO ma już niezliczone wątki dotyczące eval() w Pythonie.Python - książka Zelle używa eval(), czy to źle?

Ryzykując, aby zaprosić gniew i spadki SO, zdecydowałem się zadać to pytanie, na wszelki wypadek. Proszę, weź mnie. Wypróbowałem Google i SO sam dla tego konkretnego pytania (jak widać) i nic nie dostałem. Może jednak jestem ślepy.

To pytanie dotyczy użycia notorycznej funkcji eval().

Jest stosunkowo dobrze znana (i dobrze przeglądowi, jak widać) książka Johna Zelle: http://www.amazon.com/Python-Programming-Introduction-Computer-Science/dp/1590282418/ref=pd_sim_b_3

Technicznie rzecz biorąc, jest to książka, która wykorzystuje CS1 Python jako język programowania. Uczciwy, ten rodzaj bierze na siebie odpowiedzialność z barków autora ("Hej, próbuję cię tutaj nauczyć czegoś szerszego, nie wszystkie te szczegóły składni i bezpieczeństwa"), ale kiedy zacząłem czytać, zauważyłem, że dosłownie pierwszy przykład, wykorzystanie

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

gdzie x powinno być int a więc musimy konwertować dane wprowadzone przez użytkownika do wew.

Używam Pythona 2.7.4, a książka jest o Pythonie 3, więc od samego początku miałem sporo problemów z print() i input() oraz eval() i musiałem zrobić kilka badania, aby przykłady zadziałały. W trakcie moich badań czytałem niezliczone opinie o eval() w Pythonie (głównie tutaj na SO), które sprowadzają się do tego, że prawie zawsze jest złe, ryzyko bezpieczeństwa, niepotrzebne obciążenie techniczne i tak dalej. Pytania użytkowników były dużo bardziej skomplikowane (jeden z nich dotyczył używania eval() podczas wykonywania projektu wxPython), więc nie mogę ręczyć za całkowite podobieństwo między moim przypadkiem a ich przypadkami, ale nadal ...

Przyznaję więc, że nie jestem zbyt daleko w książce, ale doszedłem do punktu, w którym, nieco później, autor wyjaśnił użycie eval() bez żadnego odniesienia do jego kontrowersyjnej natury. W zasadzie powiedział to, co właśnie powiedziałem: potrzebujemy x, aby ostatecznie być int, więc jest to przydatny sposób na zrobienie tego. I wydaje się, że używa go zawsze.

Moje pytanie brzmi następująco: jeśli od samego początku autor popełnia taki błąd (czy NIE jest to błąd?), Może coś tu nie istnieje), czy jest to książka, od której warto się uczyć? Wierzę, że pan Zelle jest świetnym nauczycielem CS i pokazuje, ale niezależnie od tego, czy tego chce, czy nie, ludzie będą nadal uczyć się Pythona również z jego książki, oprócz algorytmów i sztuki programowania. Czy warto zatem nauczyć się Pythona z książki, która milczy nad tak pozornie uniwersalnym zagadnieniem w społeczności Pythona? Nie chcę, aby pan Zelle był hackerem w Pythonie i odkrywał wszystkie jego sekrety, ale takie małe szczegóły mogą złamać kogoś, kto sam się uczy/sam się uczy. Jaka będzie twoja rada w odniesieniu do tego materiału do nauki?

P.S. Z drugiej strony, sprawienie, że od samego początku robię sporo badań i eksperymentów (nieświadomie) jest całkiem niezłe :-)

Dziękuję!

+0

Myślałem, że eval był zły tylko w JavaScript –

+5

@JasonSperske Zło jest wszędzie – jamylak

+4

Sugerowanie eval() zamiast int() wydaje się błędne. –

Odpowiedz

9

Jako autor tej książki, pozwól mi rozważyć tę kwestię.

Wykorzystanie eval w książce jest w dużej mierze historycznym artefaktem konwersji z Python 2 na Python 3 (chociaż ta sama "usterka" istnieje w używaniu danych wejściowych w Pythonie 2). Doskonale zdaję sobie sprawę z niebezpieczeństw związanych z używaniem eval w kodzie produkcyjnym, gdzie dane wejściowe mogą pochodzić z niezaufanego źródła, ale książka nie dotyczy kodu produkcyjnego dla systemu opartego na sieci; chodzi o naukę CS i zasad programowania. W książce nie ma nic, co mogłoby być zdalnie traktowane jako kod produkcyjny. Moim celem jest zawsze zastosowanie najprostszego podejścia, które pozwala mi zilustrować punkt, który próbuję wprowadzić, i eval pomaga to zrobić.

Nie zgadzam się z tłumem głoszącym eval evil we wszystkich kontekstach. Jest bardzo przydatny w przypadku prostych programów i skryptów, które są uruchamiane tylko przez ich autora. W tym kontekście jest całkowicie bezpieczny. Pozwala na proste wiele wejść i wyrażeń jako wejście . Pedagogicznie kładzie nacisk na koncepcję oceny wypowiedzi. Eval ujawnia całą moc (i niebezpieczeństwo) interpretowanego języka. Używam eval cały czas w moich osobistych programach (i nie tylko w Pythonie). Z perspektywy czasu, absolutnie zgadzam się, że powinienem wziąć pod uwagę dyskusję na temat potencjalnego ryzyka eval; to jest coś, co zawsze robię na moich zajęciach.

Najważniejsze jest to, że istnieje wiele sposobów na ulepszenie tej książki (zawsze są). Nie sądzę, że używanie eval jest fatalną wadą; Jest to właściwe dla rodzajów ilustrowanych programów i kontekstu, w którym te programy się pojawiają.Nie jestem świadomy żadnej innej "niepewności" w sposobie używania Pythona w książce, ale powinieneś być ostrzeżony (jak wyjaśnia Wstęp), że istnieje wiele miejsc, w których kod nie jest dokładnie "Pythoniczny".

+5

Czy po prostu przyłączyłeś się do StackOverflow, aby odpowiedzieć na to? Wow, dobrze na tobie, szczerze, że publicznie zareagowałeś, zainteresowałeś się swoją książką (uczę się Pythona). Zawsze cieszę się, że autorzy na tej stronie angażują innych programistów. Mam nadzieję, że bycie obok tej strony uczyni cię lepszym pisarzem i nauczycielem oraz z szacunkiem i szczerością, zapraszamy do Stack Overflow :) –

+0

Myślę, że najlepsze książki to te, w których autor jest dostępny. Być może twój trzeci dodatek byłby lepszy pod tym względem. Biorąc to pod uwagę, nie zgadzam się z tobą, że użycie eval() jest kwestią "pytoniczną". Uważam, że to podstawowa kwestia, czy czytelnicy książki nauczą się robić rzeczy poprawnie, czy też nie. Zgadzam się z tobą, że powinieneś wspomnieć o lukach w zabezpieczeniach, które mają twoje skrypty, lub, jeszcze lepiej, napisać kod Pythona 3, który nie cierpi z powodu historii szybkiej konwersji z kodu Python 2. – Kaydell

2

Tak, eval należy zamiast tego wpisać słowo evil, aby ostrzec ludzi o tym;) Powinieneś spróbować i nigdy go nie używać, chyba że musisz. W tym przypadku intuicyjne jest używanie int() zamiast tego, jest jeszcze bardziej czytelne!Także, jeśli naprawdę musiałeś, mógłbyś użyć ast.literal_eval (ocenia tylko literały, jak wskazuje nazwa, więc nie pozwoli użytkownikowi na uruchomienie złośliwego kodu), który jest rzeczywiście bezpieczny, ale nie ma takiej potrzeby i nie ma potrzeby dla eval() w tym przypadku.

+0

Dziękuję! Moje pytanie brzmiało jednak nieco więcej o twojej opinii na temat tego kodu, który jest obecny w książce CS-Python od szanowanego profesora, którego początkujący teoretycznie powinni całkowicie ufać. Czy to zła książka, czy tylko jeden drobny błąd, który popełnił, nie powinien mówić wiele więcej o jakości materiału? – Leo

4

Od eval jest tak nie na miejscu i niepotrzebne w podanym przykładzie, z pewnością miałbym wątpliwości co do bezpieczeństwa innych części książki. Czy autor sugeruje dołączenie wprowadzonego ciągu znaków do zapytania SQL?

Myślę, że warto byłoby znaleźć adres e-mail autora i zapytać go o to bezpośrednio.

+0

Dziękujemy! Zastanawiałem się nad zrobieniem tego, ale kim teraz jestem, by zadać pytanie profesorowi CS? Jestem po prostu hobistą półprogrammistą z bardzo małą ilością projektów pod moim pasem. Mój stopień uniwersytecki nie ma nic wspólnego z komputerami ani żadną technologią. Bardziej prawdopodobne jest, że jestem tu idiotą, a nie on. To po prostu dziwne ... Książka, która jest używana na uniwersytetach, na pewno ktoś by zadał to pytanie, ale Google nic nie daje. – Leo

+0

@Gleb - Ale nie kwestionujesz używania 'eval' wyłącznie na podstawie własnej wiedzy. [Nie jesteś sam na tym] (http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html), więc po prostu idź i zapytaj. Co masz do stracenia? – root

+1

Znalazłem adres e-mail autora i zapytałem go o to. Wszyscy mówią, że jest świetnym facetem, więc mam nadzieję, że się na mnie nie wścieknie :-) Nawet jeśli początkującym nie zależy na bezpieczeństwie, zawsze niezadowoleni jest przesłanie fragmentu kodu gdzieś na takiej stronie i napotkać przeszkodę. ... no cóż, nie nienawidzę, oczywiście, ale zapał krytyki na wzór "Kto cię tego nauczył TO W ten sposób 0_o?!" – Leo

3

Cóż, połączenie eval() i input() w taki sposób tworzy elementarną, ale możliwie bardzo szkodliwą "powłokę". Nie czytałem książki, ale wziąłbym ją z przymrużeniem oka. To nie tylko zła praktyka, lecz jedno śmiertelne połączenie funkcji.

5

Tak, jest źle. Ale myślę, że wiem, dlaczego tam jest.

Wiele osób korzysta z input() w Pythonie 2.x, który jest bardzo niestety nazwaną funkcją, ponieważ nie tylko odczytuje dane wejściowe, ale także je ocenia. Konwerter 2to3 przekształca każdą wykorzystanie input() do eval(input()), jak widać:

$ 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 

Więc domyślam się, że to jest tylko trochę niechlujny. Z opisu Amazon:

Jest to druga edycja Johna zelle w Python Programming, aktualizowane dla Pythona 3.

Myślę, że ktoś prowadził 2to3 na wszystkich próbkach kodu bez sprawdzania wyjście wystarczająco dokładnie . Więc tak, błędem było użycie input() w Pythonie 2.x i błędem było użycie 2to3 bez sprawdzania danych wyjściowych.

+2

Myślę, że masz rację ze swoim małym śledztwem, ale problem polega na tym, że autor faktycznie komentuje użycie eval() bez ujawniania jakichkolwiek implikacji. Jeśli jedynym celem tego wydania (jak jest niejasno stwierdzone na wstępie) jest Python 3, to jego Python 3 powinien być, dobrze, poprawny w Pythonie 3, a nie tylko ślepą aktualizacją. Cały powód tworzenia Pythona 3 w taki sposób, w jaki on jest, rozwiązuje tego rodzaju problemy. Myślę, że każda książka powinna wziąć to pod uwagę. – Leo

+2

Więc błąd autora był z pierwszą edycją, kiedy nie używano raw_input() –

Powiązane problemy