No, byłem. Co do konferencji jako takiej to wolę się nie wypowiadać, ale wnioskuję, że nie byłem jej targetem — był może jeden wykład, na którym dowiedziałem się czegoś nowego i jeden, który obejrzałem dla przyjemności. Aspekt społeczny w pewnym stopniu został zaspokojony przez bratanie się z kolegami z Allegro.pl. Infrastrukturę (dostęp do sieci, wyżywienie, zakwaterowanie, napoje, przekąski) pominę milczeniem. W końcu też w niedzielę dałem spicz i odniosłem wrażenie, że pomimo pewnych problemów technicznych się podobał. Czyli: pod względem merytorycznym niejaki sukces.
Dla uzupełnienia:
-
prezentacja do obejrzenia/ściągnięcia jest na SlideShare
-
kod w takiej wersji, jaka była prezentowana, jest na BitBucket
Jeżeli czas pozwoli, to skrobnę też jakiś artykuł na podstawie tego, co zostało powiedziane.
Megiteam.pl w swoich dokumentach pomocy proponuje jeden sposób na oddzielenie swojego środowiska Pythona od systemowego, a także na ustalenie wersji Pythona, z jaką ma być uruchamiana aplikacja. Metodą prób i błędów doszedłem do innego, jak mi się wydaje także lepszego, sposobu na osiągnięcie tego celu.
Virtualenv na pomoc
Virtualenv to obecnie najpopularniejszy sposób na wirtualizację środowiska uruchomieniowego aplikacji. Mocno korciło mnie, by go wykorzystać do oddzielenia środowiska aplikacji od Pythona dostarczanego przez Megiteam.pl i w końcu się udało. Potrzebny będzie do tego plik virtualenv.py z dystrybucji źródłowej virtualenv. Kopiujemy go sobie w jakieś poręczne miejsce, np. do ~/.. Potem już idzie normalnie:
~$ mkdir v
~$ python2.5 virtualenv.py v/chrzczone
New python executable in v/chrzczone/bin/python2.5
Also creating executable in v/chrzczone/bin/python
Installing setuptools................done.
~$ cd v/chrzczone/
~/v/chrzczone$ bin/easy_install -U -Z psycopg2 \
Django pytz Babel BabelDjango \
django-registration django-tagging-ng \
django-pagination
Po kilku minutach mamy już swoje środowisko w katalogu $HOME/v/chrzczone. Pozostaje tylko ustawić aplikację tak, żeby wiedziała kto tu rządzi. Do tego służy plik .environment w katalogu aplikacji. Oto jak on wygląda w mojej przykładowej aplikacji o nazwie "chrzczone":
PATH=$HOME/v/chrzczone/bin:/usr/local/python2.5/bin:$PATH
PYTHONPATH=$HOME/v/chrzczone/lib/python2.5/site-packages:/usr/local/python2.5/lib/python2.5/site-packages
Wszystko w tym momencie powinno działać, ponieważ pliki .environment są dołączane kaskadowo i zmienne zdefiniowane w nich nadpisują zdefiniowane wcześniej. Ale jest również lepsza (mniej podatna na błędy) metoda osiągnięcia tego samego — żeby wszystko zagrało wystarczy, że plik .environment będzie zawierał tylko jedną linijkę:
source $HOME/v/chrzczone/bin/activate
(dzięki, Eluś, masz u mnie piwo w Ustroniu).
Ale po co to wszystko?!
A choćby po to, żeby łatwiej można było tym zarządzać, np. przy robieniu deploymentu przy użyciu Pavera. Virtualenv obecnie staje się standardową metodą zapewniania rozdzielności środowisk uruchomieniowych Pythona, dającym tyle izolacji, ile się chce. Jest wygodne i bardzo upraszcza obsługę takiego zwirtualizowanego środowiska, zwalniając z konieczności ręcznego ustawiania zmiennych środowiskowych — wystarczy zaimportować w powłoce skrypt aktywujący środowisko i wszystko jest na swoim miejscu. A jeżeli używa się virtualenvwrapper to rzeczy proste stają się jeszcze prostsze (workon, mmm...).
Uwaga, to już nieaktualne!
Będę miał 2 wolne miejsca w samochodzie z Wołomina/Warszawy do Ustronia na wyjazd na PyCon PL 2009, a o ile nie rozbiję się w drodze na konferencję to także z powrotem. W związku z tym, że jest to Escort kombi, to ta propozycja raczej nie jest skierowana do koszykarzy, chyba że mają odpinane nogi... Szczegółów organizacyjnych jeszcze nie mam, ale najprawdopodobniej wyjazd z Warszawy będzie w piątek wcześnie rano (około 7), a w drogę powrotną będę wyruszał w niedzielę tuż po śniadaniu (10?).
Kontakt Jabberem lub mailem na jarek.zgoda na GMailu. Jak sądzę, na stronie samochodowej swatki (dostępna dla potwierdzonych uczestników konferencji) także będzie możliwe skontaktowanie się ze mną, ogłoszenie tam umieszczę jak tylko organizatorzy potwierdzą mój udział.
Ponownie brudzę sobie ręce w aplikacji zrobionej przy użyciu alternative stack (Werkzeug + Jinja2 + SQLAlchemy + WTForms), trochę przy okazji przygotowań do mojego nadchodzącego wystąpienia na PyconPL 2009. I ponownie wszystko szło gładko, dopóki nie musiałem zabrać do autentykacji uwierzytelniana (nie autoryzacji).
Krąży po mieście plotka, że najlepiej do tego użyć AuthKit lub repoze.who. Jak w każdej plotce, w tej także może być ziarno prawdy, więc kilka dni temu postanowiłem to sprawdzić. Już początki nie były zachęcające (każda z tych bibliotek doinstalowuje w zależnościach połowę Pylons), a potem było jeszcze gorzej.
AuthKit okazał się tak mocno związany z Pylons, że nawet nie ma własnej dokumentacji, tylko jakieś rozdziały w Pylons Book. Jedyne, co nadawało się do użycia bez Pylons, to kilka przykładów w repozytorium. Spróbowałem pokonać niechęć i zapoznać się bliżej z tą biblioteką, ale dałem za wygraną po godzinie zastanawiania się, jak do tego bydlaka podejść. Może jakoś niedługo przyjdzie mi do głowy idea, jak mógłbym z tego skorzystać bez Pylons (a może ktoś to opisze...).
Dokumentacja do repoze.who okazała się dużo lepsza, ale tym razem przerosła mnie idea tej biblioteki. Przeczytałem wprowadzenie i zagotowało mi się pod kopułą — jak to w ogóle działa? I najważniejsze, jak to podłączyć do istniejącego kodu? Jestem pewien, że dokumentacja dokładnie opisuje każdy aspekt działania tej biblioteki, ale ja tego zwyczajnie nie zrozumiałem. Może dlatego, że przez cały czas przed oczami miałem mój use case, który obejmuje jedynie mały fragmencik tego, do czego ta biblioteka została stworzona.
Na dzień 10 lipca 2009 roku konkluzja jest taka, że albo przysiądę fałdów i spróbuję użyć jednej z tych dwóch bibliotek, albo pójdę na skróty i użyję RPX (czy czegoś w tym stylu). Co biorąc pod uwagę obecny trend w branży nie wydaje się być takim głupim rozwiązaniem. Niestety, pomijając całkowite niedopasowanie tego rozwiązania do docelowej grupy użytkowników mojej aplikacji...
Jeżeli ktoś jeszcze się zastanawia, czy wybrać się na PyconPL do Ustronia w październiku, to może przekonam go tym, że będę tam trzymał spicz na temat przygód Adama Słodowego w krainie ramówek webowych — rozłożę na czynniki pierwsze jakąś ramówkę (pewnie będzie to najbliższe mi Django) i spróbuję złożyć coś podobnego używając zamienników.
Dawno nie dawałem żadnego występu publicznego (od ostatniego WarPY w październiku minie 2 lata...), więc trzeba przygotować lepszy show. :)
Wiele było już głosów, że setuptools jest pełne błędów i nie powinno być używane. W mojej praktyce na te błędy nie trafiałem, więc poprzestawałem na niechęci, a drobne wpadki powodowały jedynie wzrost przychylności wobec antagonistów setuptools. Tym razem w ciągu ostatnich dni zostałem doświadczony dwukrotnie przez poważne niedoróbki w setuptools, w tym jedna ma znaczenie krytyczne (nie instaluje się część zawartości pakietu):
Setuptools musi odejść!
Nie nie chodzi o żadne feedy, tylko o tzw. resident set aplikacji w Django. Obserwuję tę wartość od dłuższego czasu dla tej małej aplikacyjki i z pewnym niepokojem obserwuję jak rośnie, od ~15MB pod koniec 2007 roku przez ~17MB w okolicach wydania 1.0 do ~19MB z wersją 1.1-beta1 (przy wręcz zmniejszającym się feature secie aplikacji). A mój niepokój bierze się z mojej zadziwiająco dobrej pamięci, jak na mój podeszły wiek.
Kiedyś, w zamierzchłych czasach (okolice Slackware 9.0, czyli początek 2003 roku), była sobie fajna, mała przeglądarka WWW, która nazywała się Phoenix. Wyrosła z potrzeby istnienia po prostu przeglądarki i w swoich bebechach była Mozillą (tak się kiedyś nazywała przeglądarka wyrosła z Netscape Communicatora) bez wszystkiego tego, co nie służyło przeglądaniu stron WWW. Była szybka, miała małe wymagania i wszyscy ją pokochali od razu. Pokochali ją tak bardzo, że Mozilla Foundation postanowiła skupić na niej swoje wysiłki developerskie. W szybkim tempie (od wersji 0.4 Oceano z listopada 2002 do wersji 0.8 Royal Oak z lutego 2004) program zbliżył się apetytem na zasoby do swojego rodzica i przestał być postrzegany jako lekki i szybki. Po 7 latach istnienia Mozilla Firefox wciąż bohatersko zwalcza bloat, który był głównym powodem jego wypączkowania z projektu Mozilla Suite.
Na ile ostatnie develpmenta w Django przypominają to, co stało się z Phoeniksem? Na tyle, że nagle wszyscy pokochali Django i zaczęło ono obrastać w rzeczy, które już nie mieszczą się w legendarnych 80% (i django.contrib.gis to naprawdę mały pikuś w tym zestawie). Wygląda na to, że zadowalanie coraz większej rzeszy użytkowników daje w wyniku coraz większe zapotrzebowanie na zasoby...
Rekapitulując, ja też uważam, że martwię się na zapas. Sytuacja sama w sobie nie wygląda jeszcze na niepokojącą, niepokojący jedynie może być ten trend. Czy doprowadzi do tego, że Django przejdzie na ciemną stronę mocy, to się dopiero okaże.
Zmiany się szykują... Wspominałem o planach przepisania silnika tego bloga przy użyciu narzędziówki, ale im dłużej nad tym siedzę, tym bardziej jestem przekonany, że nie ma to wielkiego sensu — zbyt wiele rzeczy wymagałoby ręcznej ingerencji, patchowania komponentów i rwania włosów z głowy, bo coś nie działa, jak na przykład odkrycie z wczoraj:
-
nie działa Beaker z powodu błędu w kodzie backendów sesyjnych wykorzystujących bazę danych i memcached (pliki działają OK, ale ich nie chcę);
-
w związku z tym, że nie działa Beaker, nie działa też AuthKit, więc nici z ułatwień autentykacji (np. po OpenID).
Oczywiście, byłbym w stanie naprawić Beaker'a, powstaje jedynie pytanie, czy to się w ogóle opłaca? Alternatywą jest przejrzenie i odchudzenie istniejącej aplikacji w Django, a przy okazji zoptymalizowanie jej nieco, wykorzystując doświadczenie, jakiego nabrałem w ciągu tych kilkunastu miesięcy. To też mogłoby być nienajgorsze rozwiązanie, a na pewno szybsze. Będę żałował Jinja2, ale jak mnie żal przyciśnie, to podłączę sobie ten silnik do Django, żeby stonować trochę ten żal...
Poważnie się zastanawiam i jeszcze nie podjąłem żadnej decyzji — na razie kod wykorzystujący narzędziówkę poszedł do oddzielnego brancha w repozytorium, a w trunku pojawił się kod wersji działającej obecnie, ale nie ma to jakiegoś symbolicznego znaczenia (tak sobie to tłumaczę). Uch, jak ja lubię mieć takie dylematy... :)
Jestem po kilku tygodniach dłubania aplikacji webowej przy użyciu zestawu narzędzi (Werkzeug, SQLAlchemy lub datastore, Jinja2, WTForms) zamiast Django. Zawsze uważałem Django za kawał świetnego softu, ale dopiero teraz doceniam to, na ile ramówka aplikacyjna ułatwia życie programisty, załatwiając masę rzeczy z kategorii boilerplate przy użyciu kawałka swojej magii.
Narzędziówka jest pozbawiona zupełnie magii. To surowy zestaw narzędzi (niektóre z nich, jak SQLAlchemy mają własną magię wewnętrzną do załatwiania swoich spraw) i żeby zagrały ze sobą w zgodnej orkiestrze i razem umożliwiły napisanie dobrego kodu aplikacji, trzeba napisać sporo rzeczy: procesory żądań (w Django nazywa się to middleware), procesory kontekstu, podsystem konfiguracyjny, skróty ułatwiające życie (jak render_to_response() czy funkcja do odwracania URL-i), podsystem autoryzacji. W Django to wszystko już jest, gotowe i zainstalowane, a użycie jest tylko kwestią podłączenia w konfiguracji lub nawet zaimportowania odpowiedniego modułu — i za sprawą magicznej różdżki masz sitemapę, masz feed RSS/Atom, masz bufor stron i masę innych drobiazgów, na napisanie których poświęciłbyś trochę czasu, bo trzeba to mieć, pomimo tego, że te wszystkie rzeczy nie są corem aplikacji. Łatwo jest to wszystko docenić: działające zręby bloga w Django (tego bloga) miałem po około 2 godzinach roboty (wpisy, etykiety, archiwum, feed z wpisów i sitemapa), a powtórzenie tego samego wyczynu z użyciem zestawu narzędzi zajęło mi ponad 6 godzin pracy, z czego co najmniej 3 spędziłem na użeraniu się z duperelami. Warto było, bo moja wiedza na temat działania aplikacji w środowisku WSGI jest teraz o wiele większa. I lepiej rozumiem bebechy Django.
Z drugiej strony nie można powiedzieć, żeby ta wyprawa miała jedynie edukacyjną wartość — dorobiłem się sporej ilości kodu narzędziowego, który może mi się kiedyś przydać. Zobaczyłem też, jak wydajna i oszczędna w wykorzystaniu zasobów może być mała aplikacja, jeżeli się ją rozsądnie napisze, dla porównania aplikacja tego bloga żre na megiteam.pl ~20MB pamięci rezydentnej, a moja reimplementacja przy użyciu zestawu narzędzi jedynie ~12MB — różnica jest kolosalna (nie wspominam już o tym, że jest o wiele szybsza, prawdopodobnie dzięki Jinja2). Przyszłością tego bloga jest właśnie reimplementacja przy użyciu zestawu narzędzi, głównie w celach oszczędnościowych.
Napisawszy tyle wypadałoby przejść do jakiejś konkluzji... Jak dla mnie to każdy kto robi w webie przy użyciu pythonowych ramówek (nie tylko Django, to się tyczy również Pylons i TurboGears w takim samym stopniu), powinien zrobić sobie taką krótką wycieczkę do źródeł. Będzie mógł wtedy dostrzec zarówno mocne jak i słabe strony używanej przez siebie ramówki, a przede wszystkim zrozumie, jak jej wszystkie komponenty współgrają ze sobą, tworząc całość, która tak bardzo ułatwia pracę.
A to dlatego, że moje przemyślenia na temat technologii przeniosłem do technologicznej tuby tego serwisu, którą w ramach edukacji implementuję na Google AppEngine. Aplikacja, choć wciąż w trakcie rozwoju, powoli zyskuje kolejne funkcje (a ja przy okazji uczę się nowych rzeczy).