Django - zabójcza aplikacja.

Posted by Jarosław Zabiełło Sat, 27 May 2006 08:17:00 GMT

Muszę przyznać, że podoba mi się zarówno sposób, jak i kierunek, w którym rozwijany jest pythonowy framework Django. Nie jest to kolejny domowy projekt tworzony w ramach hobby (jak to było z CherryPy). Django powstawało od razu z założeniem pracy w ciężkim środowisku produkcyjnym. Ostatnio napisałem sobie (w ramach zabawy) pewną aplikację w Django i muszę przyznać, że praca z Django jest faktycznie komfortowa. Wyższa niż w Pylons, i wyższa nawet niż w Railsach. Aby tekst nie był za długi, podzielę go na kilka mniejszych tekstów. Przedstawię swoje spostrzeżenia co do Pythona jako języka na tle Rubiego. Potem opiszę powody dla których Django ma wielkie szanse stać się killer application dla Pythona. Oraz w kolejnych częściach opiszę krok po kroku tworzenie konkretnej aplikacji w Django. Dziś będzie krótko o Pythonie.

Przewaga Pythona

Gdy zaczynam mówić o Django, to od razu nasuwa mi się porównanie do Ruby on Rails. Django jest oparty na języku Python, a Rails na języku Ruby. Co by nie mówić o zaletach Rubiego, to Python posiada kilka cech, które moim zdaniem, stawiają go wyżej1:

Python jest szybszy.

To po prostu jest fakt i to widać gołym okiem. Python automatycznie kompiluje każdy moduł do bytecodu. To jest operacja całkowicie przezroczysta dla programisty. Bytecode przy dużym projekcie składającym się w setek plików przyśpiesza znacznie czas ładowania kodu i może od biedy służyć również jako proste zabezpieczenie źródeł. Python jest szybszy nie tylko od Rubiego, ale także od PHP. Robiłem kiedyś porównanie prostej aplikacji w mod_php5 vs Myghty. Zdziwiło mnie wtedy to, że Python był tu szybszy, bo PHP jest zoptymalizowany do szybkiego wykonywania prostych skryptów. Oczywiście, im większy kod, tym rośnie przewaga Pythona z powodu użycia bytecodu2.

Python jest łatwiejszy do nauki.

Pythona łatwiej można się nauczyć i posługiwać niż Rubiego czy nawet PHP (sic!). To jest bardzo ważny punkt, bo dotyczy kluczowej kwestii jaką jest produktywność programisty.

Filozofią Pythona jest aby było jak najmniej możliwych dróg do rozwiązania tego samego problemu. Z tego wynika, że Python stara się implementować jak najmniejszą ilość funkcji i metod. Znacznie to ułatwia poruszanie się po tych metodach. W wypadku Rubiego, nie dość, że mamy znacznie więcej metod na obiekt, to na dodatek, lista metod jest dodatkowo zaśmiecona aliasami. W Ruby mamy po kilka metod, które wykonują to samo. Po kilka konstrukcji językowych, które robią to samo. Widać tu korzenie fascynacji Perlem. Ale dla programistów to jest uciążliwość.

Python jest bardziej produktywny.

Dodatkowym czynnikiem ułatwiającym szybką prace, jest integracja prostego mechanizmu dokumentacji kodu na poziomie składni Pythona. Mowa o docstringach. W praktyce znaczy to, że prawie wszystkie edytory IDE (których jest sporo, są darmowe i są bardzo dobre jak na tę klasę języków) nie tylko rozwijają mniej metod, ale także wyświetlają ich zintegrowaną dokumentację. Efektem jest znacznie mniej czasu traconego na zaglądanie do dokumentacji czy książek. To duża, odczuwalna różnica. Mniej rzeczy do zapamiętania, podpowiedzi do składni na każdym kroku, to musi się odbijac na produktywności tworzenia kodu3.

Python ma pełną obsługę Unicode.

Pełnej obsługi Unicode nie ma ani PHP ani Ruby. Obsługują co najwyżej UTF-8 i to w ograniczonym zakresie. Np. próby konwersji znaków ze standardu cp1250 (typowa sytuacja dla polskiego serwera MSSQL) do latin2 (typowe dla serwera MySQL w internecie) skazane są na korzystanie z biblioteki iconv, co jest dosyć chorym rozwiązaniem. Chorym, bo iconv nie umie dawać sobie rady z wieloma znakami, które nie mają odpowiednika w standarcie latin2. Chodzi nie o polskie ogonki, ale o różnego rodzaju długie myślniki, polskie, dolne cudzysłowy itp.

>>> s = " „To jest jakiś tekst — spróbuj to skonwertować z cp1250 do latin2.”  "
' \x84To jest jaki\x9c tekst \x97 spr\xf3buj to skonwertowa\xe6 z cp1250 do latin2.\x94  '
>>> s = " „To jest jakiś tekst — spróbuj to skonwertować z cp1250 do latin2.”  "
>>> s
' \x84To jest jaki\x9c tekst \x97 spr\xf3buj to skonwertowa\xe6 z cp1250 do latin2.\x94  '
>>> u = unicode(s, 'cp1250')
>>> u
u' \u201eTo jest jaki\u015b tekst \u2014 spr\xf3buj to skonwertowa\u0107 z cp1250 do latin2.\u201d  '
>>> print uTo jest jakiś tekstspróbuj to skonwertować z cp1250 do latin2.”  
>>> latin2 = u.encode('iso-8859-2', 'xmlcharrefreplace')
>>> latin2
' „To jest jaki\xb6 tekst — spr\xf3buj to skonwertowa\xe6 z cp1250 do latin2.”  '

Nie chodzi tylko o konwersje znaków. Dzięki Unicode, w Pythonie możesz dokonywać rzeczy bardzo trudnych do uzyskania w PHP czy Ruby. Operacje na tekście potrafią poprawnie traktować polskie znaczki. Np. napisanie funkcji implementującej podświetlanie wyszukiwanych słów bez względy na to czy uzyto dużych, czy małych polskich znaków. Dla bazy SQL to żaden problem4 ale dla kodu?

Chcielibyśmy aby wyrażeniem regularnym podmienić jakieś słowa zawierające polskie znaczkiNp. wyrażenia regularne umieją reagować poprawnie na polskie ogonki!

#-*- coding: utf-8 -*-
import re
def highlight(tekst, slowo, encoding):
    if not isinstance(tekst, unicode):
        tekst = unicode(tekst, encoding)
    if not isinstance(slowo, unicode):
        slowo = unicode(slowo, encoding)
    replace = re.compile('('+re.escape(slowo)+')', re.I|re.U).sub
    return replace(r'<b>\1</b>', tekst)
print
print highlight("podświetl gęś GĘŚ, GęŚ", "gęś", 'cp1250') 
# => podświetl <b>gęś</b> <b>GĘŚ</b>, <b>GęŚ</b>

Jeszcze jedno. Microsoft “uszczęśliwił” nasz kilkoma standardami kodowania polskich znaków. Inny jest dla windows (cp1250) a inny dla konsoli okienka DOS (cp852). Python pozwala całkowicie zapomnieć o stringach i kodowaniach. Po prostu należy pracować na obiektach Unicode. Powtarzam: obiektach Unicode a nie stringach UTF-8, bo to nie to samo. Instrukcja print wyświetli poprawnie polskie znaki, jeśli operujemy na obiekcie unicode.

Python ma stabilniejsze i dojrzalsze biblioteki.

Przekonałem się na swojej skórze, co znaczy przekonwertować setki plików graficznych za pomocą biblioteki RMagick (Ruby), a za pomocą PIL (Python). Kod w Ruby pożarł mi cała pamięć i odmówił pracy…

-

1 Osobną kategorią jest język PHP. Właściwie szkoda gadać. Ci, co zakosztowali pracy z Pythonem i Ruby, tracą szybko zapał do mozolnego dłubania w chaotycznym, niespójnym, źle zaprojektowanym języku PHP. Na ten temat to chyba trzeba napisać oddzielny tekst. Jak znajdę czas, to sobie “poużywam” na PHP. :)

2 Aby PHP aż tak nie odstawał, trzeba użyć akcelerator. Niektóre złożone projekty PHP, jak ezPublish, bez akceleratora są koszmarnie wolne.

3 Najlepszym przykładem różnicy między Pythonem a np. .NET jest ostatnio zaimplementowany przez mnie system synchronizacji danych między serwerami. Projekt tworzony przez 6 miesięcy w VB.NET (.NET) został napisany od zera w 5 roboczych dni (z czego działający prototyp był dostępny po paru godzinach). Żeby było ciekawiej, nowy kod Pythona w tym wypadku działa i szybciej i stabilniej.

4 Np. dla MySQL (od wersji 4.1 wzwyż) trzeba tylko ustawić aby baza pracowała natywnie w utf8 (domyślnie jest latin1) i tabele oraz ich pola tekstowe miały ustawiony parametr collations na utf8_polish_ci.

(Zobacz: część II)

Posted in ,  | Tags  | 6 comments

Comments

  1. Avatar Adamh said about 19 hours later:

    Co do przewagi Pythona nad Rubym zgodze sie z tymi argumentami ale warto nadmienic dlaczego tak wiele osob stawia Ruby na piedestale (np ja). Moim zdaniem kod pisany w Rubym jest tak bardzo przejrzysty, ze praktycznie nie wymaga komentowania. Tworzenie tego kodu jest wrecz zabawa (trzeba to poczuc programujac wczesniej w PHP lub Javie). Moim zdaniem w Rubym programuje sie szybciej (fakt, ze lepiej znam Ruby niz Pythona ale nadrabiam:)) Wiele osob chwali Pythona za jedno dobre rozwiazanie – dla mnie piekny jest wybor rozwiazania i drogi wg moich preferencji (fakt, ze ktos musi sie wtedy na inne do swego podejscie przestawic).

    Django jest inne niz Rails tak jak Python inny niz Ruby i na pewno znajda sie ludzie preferujacy jedna lub druga filozofie. Piekne jest to, ze powstaja naprawde dobre alternatywy.

  2. Avatar Pawel Rutkowski said about 20 hours later:

    Apropo stabilniejszych bibliotek dla Pythona. Mozesz przytoczyc jakies dodatkowe przyklady ? Bo takie stwierdzenie na podstawie jednej biblioteki jest malo obiektywne.

    Juz wczesniej pisalem ze robilem cuda na RMagicku+GraphicsMagick i na takie problemy nie trafilem.

  3. Avatar Jarosław Zabiełło said about 24 hours later:

    Adamh: to prawda, że kod Rubiego jest bardzo elegancki. Ale mam wrażenie, że jak się w tym człowiek zagłębia, to znacznie łatwiej się pogubić. Nie wiadomo skąd pojawiają się jakieś metody i funkcje. Masz kupę includowanych plików (require) które ładują kolejne i gdzieś w tym łańcuchu coś jest odpalone, coś innego dodane do przestrzeni nazw.

    Będę się upierał, ale wolę minimalistyczne podejście Pythona. Wolę jak mi edytor rozwinie 10 metod do obiektu a nie 1000 z czego połowa to aliasy (oczywiście przesadzam ;). Co do konstrukcji języka, to bym może nie był już tak zasadniczy, bo to mi nie przeszkadza (składnia Rubiego mi się podoba). Przeszkadza mi tylko nadmiar metod i ich duplikacj oraz sposób dodawania czegoś do przestrzeni nazw.

    Paweł: Ja tylko opisuję swoje wrażenia. Poza RMagickiem miałem także nieprzyjemny epizod z modułem mysql do windozy. Wywalał mi core dump. Na szczęście pomógł późniejszy upgrade. Python jest szerzej stosowany i to na sporą skalę (Google, NASA itp.) – wydaje mi się to raczej oczywiste, że jego biblioteki są lepiej dopracowane. O Ruby tak naprawdę zaczęto szerzej mówić dopiero od czasu powstania Railsów.

  4. Avatar Adamh said 1 day later:

    W tych minusach zgadzam sie (pojawily sie one juz w tekscie). Przestrzen nazw – wspaniala rzecz, tak jak docstringi i proba minimalizowania aliasow metod.

    PS z tego co wiem to NASA i ponoc Google uzywaja rowniez Ruby’ego :) Oczywiscie nie na taka skale jak Pythona (szczegolnie Google jak wiadomo).

    Python stal sie bardzo popularny sam w sobie jako jezyk. Ruby stal sie bardzo popularny jako fundament Railsow – choc to rowniez sie zmienia. Ciekawy jestem jaki bedzie Ruby 2.0

  5. Avatar skk said 19 days later:

    jesli moge sie dolaczyc: nie jestem programista, chociaz przecioralem sie w swoim zyciu przez rozne kursy C, C++, VB, HTML etc etc, bo wydawalo mi sie, ze ktos, kto uzywa komputera profesjonalnie, powinien wiedziec “czym to sie je”. Co jakis czas potrzebuje napisac sobie proste narzedzie i z tego punktu widzienia Python jest dla mnie zbawca. Nigdy nie naczyłbym sie programowac (nawet na tak podstaworym poziomie) gdyby nie Python. Jego zadziwiajaca prostota moze umykac profesjonalnym programistom. Dla takich ludzi jak ja, to zupelnie podstawowa sprawa: to, ze kod pythona wyglada jak pseudokod. Otoz z Rubym juz tak nie jest. Wiem, ze to dobrze zaprojektowany program i elegancki, ale co mnie zrazilo do niego, to stosowanie roznych “kruczkow” dla szybszego zapisywania kodu. Nie przypomne sobie teraz przykladu, ale juz na drugiej lub trzeciej lekcji w Rubym pojawiaja sie “sposobiki” jak cos ujac w sposob mniej czytelny, ale za to szybszy. Natymiast zaczalem sie gubic. No i do tego moduly w Pythonie… :) rzeczy niemozliwe dla nie bez Pythona, stoja otworem. Z tego co wiem, mimo swej porazajacej prostoty, to bardzo potezne narzedzie, w przeciwienstwie do VBasica.

  6. Avatar daniel- chazol@poczta.fm said 3 months later:

    czesc mam pytanko szukam wszedzie po internecie czegos na temat UNICODE czy posiadasz wiedze na ten temat. prosze o kontakt gg 4014674 email chazol@poczta.fm

(leave url/email »)

   Comment Markup Help Preview comment