AppEngine i Pylons
Wszyscy piszą o Google AppEngine więc ja też coś napiszę. Żeby nie było tylko Django i Django zawiadamiam, że trwają prace nad uruchomieniem Pylonsa na Google’u.
Najwięcej kłopotów było z faktem, że na AppEngine nie można instalować bibliotek używających C. Okazuje się, że Mako i SQLAlchemy są takowymi. O ile SQLALchemy nie jest może w tym przypadku istotne o tyle Mako by się przydało.
Jak można było się spodziewać, na developerów Pylonsa można liczyć. Trunk Mako można już instalować na AppEngine a Beaker może pracować z Googlowym silnikiem baz danych.
Ian Bicking wypuścił pakiet umożliwiający zbudowanie środowiska do AppEngine.
Więcej informacji w poście:
http://groups.google.pl/group/pylons-discuss/browse_thread/thread/3f132217b134b772
Instrukcja jak zrobić i zainstalować na AppEngine aplikację w Pylonsie:
W pogoni za wersjami
Frameworki, szczególnie w językach dynamicznych bardzo szybko się rozwijają. Powstaje wersja za wersją. Przy większej liczbie aplikacji może to być uciążliwe.
Aplikacje pisane pół roku temu są kompatybilne z wersją 0.x frameworka, po drodze były wersje 0.x.y, 0.y a teraz jest wersja 0.z. Czy tkwić z jedną ustaloną jako produkcyjna wersją czy używać do nowych projektów aktualnie najnowszej. Przecież na serwerze jest zainstalowana wersja 0.x i nie ma szans na podniesienie i sprawdzenie wszystkich aplikacji.
W rozwiązaniu tego dylematu pomógł pakiet “virtualenv”. Za jego pomocą szybko zrobimy wirtualne środowisko pythona.
Może przykład z Pylonsem: na serwerze jest zainstalowana wersja 0.9.5 a najnowszą wersją jest 0.9.6, która ma sporo zmian.
Więc instalujemy pakiet virtualenv:
easy_install virtualenv
Robimy środowisko:
virtualenv 096
Powstał nowy katalog “096” z binarką pythona. Instalujemy nową wersję Pylonsa:
cd 096
./bin/easy_install Pylons==0.9.6
Wgrywamy naszą aplikację do jakiegoś podkatalogu np. Aplikacja i uruchamiamy:
cd Aplikacja
../bin/paster serve production.ini --daemon start
I gotowe. Możemy sobie dograć niezbędne wersje bibliotek. Trzeba pamiętać aby używać skryptów jawnie podając katalog 096/bin.
Co robią moje wątki?
Paster dostarcza wiele przydatnych aplikacji. Jedna z nich nazywa się watch_threads i służy do podglądania stanu wątków pastera.
Widzimy ile wątków jest w puli, ile aktualnie jest używanych, czy są jakieś zablokowane. Jest też lista wątków aktualnie przetwarzanych oraz kilka szczegółów np. czas wykonania. Możemy zabijać zablokowane wątki.
Instalacja jest prosta. Jest to aplikacja wsgi więc można wpiąć ją pod url do pastera. Wystarczy zmienić domyślne sekcje w pliku .ini:
[composite:main]
use = egg:Paste#urlmap
/ = mainapp
/monitor = monitor
[app:monitor]
use = egg:Paste#watch_threads
allow_kill = True
[app:mainapp]
...
Po restarcie pod adresem: /monitor mamy listę aktualnie używanych wątków.

Paster na kilka procesów
Po przeczytaniu paru artykułów o GIL postanowiłem spróbować rozdzielić paster’a na kilka procesów.
Domyślnie Pylons rusza w trybie z pulą 10 wątków. Liczbę wątków można zmienić w production.ini umieszczając w sekcji server:main poniższe:
use_threadpool = True
threadpool_workers = 20
Ale czy 20 wątków i więcej będą optymalnie wykorzystywały wieloprocesorową maszynę? Może lepszym wyjściem jest powielanie procesów a nie wątków.
Aby uruchomić aplikację na kilku procesach można zrobić kilka sekcji server:
[server:main]
use = egg:paste#http
host = 0.0.0.0
port = 5000
use_threadpool = True
threadpool_workers = 10
[server:main2]
use = egg:paste#http
host = 0.0.0.0
port = 5001
use_threadpool = True
threadpool_workers = 10
Teraz aby wystartować robimy:
paster serve production.ini --server-name=main --pid-file=main.pid --log-file=main.log --daemon start
paster serve production.ini --server-name=main2 --pid-file=main2.pid --log-file=main2.log --daemon start
I mamy kilka procesów. Teraz wystarczy napisać kawałek skryptu startującego, ustawić loadbalancer i testować.
Ruby z punktu widzenia programisty Pythona
Ostatnio trochę bawię się railsem i zdenerwowała mnie jedna śmieszna kwestia.
A było to tak:
Robiłem model zamówienia i pomyślałem sobie, że przydało by sie pole “hash” w bazie. A tu bach wyjątek. Konflikt z funkcją “hash” podstawowego obiektu rubiego. Ok, będzie brzydko nazwałem pole po polskiemu “hasz” :(
Idziemy dalej: model do wymiany danych za pomocą xml’a. Wymyśliłem sobie metodę “send”, która wyśle przygotowany wcześniej xml. A tu bach, metoda “send” obiektu rubiego. Ok, bedzie “send_xml”.
Cholera, każdy obiekt ma ponad 40 publicznych metod na starcie. Teraz boję się dodawać nowe atrybuty do klasy bo nie znam dnia i godziny kiedy znowu natrafię na magiczną wbudowaną metodę :)
Ciężkie jest życie człowieka, który chce poznać nowe, fajne technologie ale przyzwyczaił się do minimalizmu pythona.