Howto: bottle + Python3.1 + uWSGI + Cherokee? - Probleme
Verfasst: Mittwoch 30. Dezember 2009, 15:33
Problemstellung
Bei meiner Suche nach einer brauchbaren und effizienten Lösung um mit Python 3 Webapplikationen zu entwickeln, bin ich bei der Kombination aus Bottle, uWSGI und Cherokee hängen geblieben.
Nach einiger Recherche bin ich auch relativ weit gekommen und habe einige Fallstricke lösen können, die ich anderen gerne hiermit ersparen möchte. Allerdings scheitert es im Moment sozusagen auf der Zielgerade und da hoffe ich nun auf eure Hilfe. Ich vermute das Problem in der Art und Weise, wie in bottle WSGI implementiert ist.
Voraussetzungen
Meine Ausgangsbasis ist eine Minimalinstallation von Ubuntu Karmic Server in VirtualBox.
Vorgehensweise
1.
Die Cherokee Version, die bei Ubuntu 9.10 (Karmic) standardmäßig dabei ist, hat leider noch keine Unterstützung für uWSGI, deswegen empfiehlt es sich die Version aus den PPA-Quellen zu nehmen. Für die spätere Kompillierung von uwsgi wird das python3-dev Paket benötigt:
2.
uWSGI ist noch nicht als Paket für Ubuntu verfügbar, deswegen muss der Quellcode heruntergeladen und manuell kompilliert werden.
3.
Leider ist im Quellarchiv der Version 0.9.3 noch kein Makefile für Python 3.1 unter Linux enthalten (Nur für Python 2.X, die Python3.X Makefiles mit UNBIT im Namen sind für normale Linux-Systeme nicht brauchbar).
Der uWSGI Entwickler Roberto De Ioris war so nett und hat mir aber eine funktionierendes Makefile zur Verfügung gestellt.
Die Datei /usr/src/uwsgi/uwsgi-0.9.3/Makefile.Linux.Py31 muss mit folgendem Inhalt erstellt werden:
4.
Danach geht es mit der eigentlichen Kompillierung weiter.
5.
Außerdem muss sich die erzeugte uwsgi Datei im PATH befinden, damit sie von Cherokee gefunden werden kann. Dazu kann man sie einfach in /usr/bin/ linken:
6.
Damit Bottle und uWSGI zusammen spielen, müssen diese erst konfiguriert werden. Dazu erzeugt man eine Datei /home/kev/bottle_site/bottle_uwsgi.conf nach folgendem Format:
/home/kev/bottle_site/ muss durch den Hauptpfad der eigenen Bottle-Anwendung ersetzt werden. app muss durch den Namen der Hauptdatei der Anwendung - ohne die Dateiendung .py - ersetzt werden.
In meinem Fall gibt es ein Verzeichnis /home/kev/bottle_site/ in der die Original bottle.py Datei liegt und meine eigene Anwendung app.py.
In app.py wird z.B. import bottle aufgerufen.
7.
Nun geht es an die Konfiguration von Cherokee, die am einfachsten über das eingebaute Webinterface erfolgt. Dazu startet man cherokee-admin:
Für die Konfiguration startet man einen Webbrowser und öffnet die von cherokee-admin ausgegebene Adresse. Im Standardfall ist das die eigene IP auf Port 9090. Benutzer ist "admin" und das Passwort wird ebenfalls von cherokee-admin ausgegeben und ist bei jedem Aufruf von cherokee-admin neu generiert.
8.
In der Konfiguration hangelt man sich nun durch folgende Dialoge durch:
Viertueller Server -> default -> Verhalten -> Wizard -> uWSGI Run Wizard
Als Konfigurationsdatei gibt man hier nun die vorhin erstellte wsgi conf Datei an. In meinem Fall ist das: /home/kev/bottle_site/bottle_uwsgi.conf.
Soweit, so gut.
9.
Damit bottle richtig auf die Anfragen von uWSGI reagieren kann, muss man sein Hauptmodul (bei mir die app.py) anpassen.
Laut http://projects.unbit.it/uwsgi/wiki/Example muss dazu eine Referenz namens "application" auf einen WSGIHandler erzeugt werden.
Das habe ich wie folgt gemacht und mich dabei an http://bottle.paws.de/page/docs#apache-mod_wsgi orientiert:
Damit sollte es eigentlich funktionieren. Aber.
Problem
Cherokee scheint die Anfragen korrekt an uWSGI weiter zu reichen.
uWSGI kann auch die Applikation aufrufen und initialisieren.
Allerdings kommt nichts brauchbares an den Browser zurück, es wird schlicht eine leere Seite ohne Inhalt angezeigt. Auch der Quellcode ist leer.
Zu Testzwecken kann man wsgi manuell starten. Die korrekten Parameter entnimmt man am Besten aus cherokee-admin -> information sources -> Nick: uWSGI X -> Interpreter.
Das X steht für irgendeine Ganzzahl.
Danach stellt man sicher, dass keine uwsgi-Prozesse laufen (ps -A|grep wsgi). Falls doch, killt man diese.
Danach startet man den Prozess von Hand im Terminal. In Meinem Fall ist das:
Wie man an der letzten Zeite sieht (generated 0 bytes in 144 msecs), ist die Seite wirklich leer.
Ab hier komme ich nicht mehr weiter. Die Applikation selbst funktioniert (über run() ohne uwsgi).
Für uWSGI und Python3 gibt es noch die Seite http://projects.unbit.it/uwsgi/wiki/RunOnPython3k mit Sachen, die man beachten soll. Allerdings betrifft das nur den Charset. Ich nehme doch an, dass ich zumindest kaputten Inhalt bekommen sollte, wenn ich das nicht beachte. In meinem Fall ist es aber gar keiner und ich weiß nicht woran das liegt, da ich mich mit WSGI usw. nicht benügend auskenne.
Ich vermute, dass die Methode __call__ in der Klasse Bottle im Modul bottle.py für die ganzen WSGI Requests letzten endes zuständig ist. Die Methodensignatur deckt sich auch mit der RunOnPython3k Seite von uwsgi.
Aber es kommt anscheinend nichts zurück.
Bin für jeden Tipp sehr dankbar und hoffe mit meiner Beschreibung jedem über die ersten Hürden helfen zu können, der Ähnliches vor hat.
Hier noch einmal zusammenfassend eine Liste mit Quellen/Seiten für weiterführende Informationen mit deren Hilfe ich diese Informationen zusammen getragen habe:
http://projects.unbit.it/uwsgi/wiki
http://projects.unbit.it/uwsgi/wiki/Install
http://projects.unbit.it/uwsgi/wiki/Doc
http://projects.unbit.it/uwsgi/wiki/Example
http://projects.unbit.it/uwsgi/wiki/RunOnPython3k
http://projects.unbit.it/uwsgi/wiki/RunOnCherokee
http://www.cherokee-project.com/doc/cookbook_uwsgi.html
http://bottle.paws.de/page/2009-12-02_release_notes_0.7
http://bottle.paws.de/page/docs#apache-mod_wsgi
http://bottle.paws.de/page/docs#how-default_app-works
Bei meiner Suche nach einer brauchbaren und effizienten Lösung um mit Python 3 Webapplikationen zu entwickeln, bin ich bei der Kombination aus Bottle, uWSGI und Cherokee hängen geblieben.
Nach einiger Recherche bin ich auch relativ weit gekommen und habe einige Fallstricke lösen können, die ich anderen gerne hiermit ersparen möchte. Allerdings scheitert es im Moment sozusagen auf der Zielgerade und da hoffe ich nun auf eure Hilfe. Ich vermute das Problem in der Art und Weise, wie in bottle WSGI implementiert ist.
Voraussetzungen
Meine Ausgangsbasis ist eine Minimalinstallation von Ubuntu Karmic Server in VirtualBox.
Vorgehensweise
1.
Die Cherokee Version, die bei Ubuntu 9.10 (Karmic) standardmäßig dabei ist, hat leider noch keine Unterstützung für uWSGI, deswegen empfiehlt es sich die Version aus den PPA-Quellen zu nehmen. Für die spätere Kompillierung von uwsgi wird das python3-dev Paket benötigt:
Code: Alles auswählen
sudo apt-get install python-software-properties
sudo add-apt-repository ppa:cherokee-webserver/ppa
sudo apt-get update
sudo apt-get install python3-dev cherokee
uWSGI ist noch nicht als Paket für Ubuntu verfügbar, deswegen muss der Quellcode heruntergeladen und manuell kompilliert werden.
Code: Alles auswählen
mkdir /usr/src/uwsgi
cd /usr/src/uwsgi
wget http://projects.unbit.it/downloads/uwsgi-0.9.3.tar.gz
tar -xzvf uwsgi-0.9.3.tar.gz
cd uwsgi-0.9.3
Leider ist im Quellarchiv der Version 0.9.3 noch kein Makefile für Python 3.1 unter Linux enthalten (Nur für Python 2.X, die Python3.X Makefiles mit UNBIT im Namen sind für normale Linux-Systeme nicht brauchbar).
Der uWSGI Entwickler Roberto De Ioris war so nett und hat mir aber eine funktionierendes Makefile zur Verfügung gestellt.
Die Datei /usr/src/uwsgi/uwsgi-0.9.3/Makefile.Linux.Py31 muss mit folgendem Inhalt erstellt werden:
Code: Alles auswählen
CC=gcc
PYTHON_CFLAGS=`python3.1-config --cflags`
PYTHON_LIBS=`python3.1-config --libs`
XML_CFLAGS=`xml2-config --cflags`
XML_LIBS=`xml2-config --libs`
CFLAGS=$(PYTHON_CFLAGS) $(XML_CFLAGS) -DPYTHREE
LD_FLAGS=$(PYTHON_LIBS) $(XML_LIBS) -DPYTHREE
PROGRAM=uwsgi31
all: clean uwsgi
uwsgi: utils.o socket.o pymodule.o main.o
$(CC) $(LD_FLAGS) utils.o socket.o pymodule.o main.o -o $(PROGRAM)
utils.o: utils.c
$(CC) -c $(CFLAGS) utils.c
socket.o: socket.c
$(CC) -c $(CFLAGS) socket.c
pymodule.o: uwsgi_pymodule.c
$(CC) -c $(CFLAGS) -o pymodule.o uwsgi_pymodule.c
main.o: uwsgi.c
$(CC) -c $(CFLAGS) -o main.o uwsgi.c
clean:
rm -f utils.o socket.o pymodule.o main.o
Danach geht es mit der eigentlichen Kompillierung weiter.
Code: Alles auswählen
make -f Makefile.Linux.Py31
Außerdem muss sich die erzeugte uwsgi Datei im PATH befinden, damit sie von Cherokee gefunden werden kann. Dazu kann man sie einfach in /usr/bin/ linken:
Code: Alles auswählen
ln -s /usr/src/uwsgi/uwsgi-0.9.3/uwsgi31 /usr/bin/uwsgi
Damit Bottle und uWSGI zusammen spielen, müssen diese erst konfiguriert werden. Dazu erzeugt man eine Datei /home/kev/bottle_site/bottle_uwsgi.conf nach folgendem Format:
Code: Alles auswählen
<uwsgi>
<pythonpath>/home/kev/bottle_site/</pythonpath>
<app mountpoint="/">
<script>app</script>
</app>
</uwsgi>
In meinem Fall gibt es ein Verzeichnis /home/kev/bottle_site/ in der die Original bottle.py Datei liegt und meine eigene Anwendung app.py.
In app.py wird z.B. import bottle aufgerufen.
7.
Nun geht es an die Konfiguration von Cherokee, die am einfachsten über das eingebaute Webinterface erfolgt. Dazu startet man cherokee-admin:
Code: Alles auswählen
cherokee-admin
8.
In der Konfiguration hangelt man sich nun durch folgende Dialoge durch:
Viertueller Server -> default -> Verhalten -> Wizard -> uWSGI Run Wizard
Als Konfigurationsdatei gibt man hier nun die vorhin erstellte wsgi conf Datei an. In meinem Fall ist das: /home/kev/bottle_site/bottle_uwsgi.conf.
Soweit, so gut.
9.
Damit bottle richtig auf die Anfragen von uWSGI reagieren kann, muss man sein Hauptmodul (bei mir die app.py) anpassen.
Laut http://projects.unbit.it/uwsgi/wiki/Example muss dazu eine Referenz namens "application" auf einen WSGIHandler erzeugt werden.
Das habe ich wie folgt gemacht und mich dabei an http://bottle.paws.de/page/docs#apache-mod_wsgi orientiert:
Code: Alles auswählen
import os
os.chdir(os.path.dirname(__file__))
#ganz am Anfang der Datei einfügen.
import bottle
# sollte sowieso schon in der bottle-Anwendung enthalten sein
# hier sind die ganzen @route Dekoratoren und alle eigenen Anweisungen.
# ganz am Ende der Datei darf run() NICHT aufgerufen werden. Stattdessen muss dort stehen:
# falls man eine neuere bottle-Version benutzt, Ich benutze direkt die von github:
application = bottle.app()
#falls man eine ältere bottle-Version benutzt und app() noch default_app() hieß:
application = bottle.default_app()
Problem
Cherokee scheint die Anfragen korrekt an uWSGI weiter zu reichen.
uWSGI kann auch die Applikation aufrufen und initialisieren.
Allerdings kommt nichts brauchbares an den Browser zurück, es wird schlicht eine leere Seite ohne Inhalt angezeigt. Auch der Quellcode ist leer.
Zu Testzwecken kann man wsgi manuell starten. Die korrekten Parameter entnimmt man am Besten aus cherokee-admin -> information sources -> Nick: uWSGI X -> Interpreter.
Das X steht für irgendeine Ganzzahl.
Danach stellt man sicher, dass keine uwsgi-Prozesse laufen (ps -A|grep wsgi). Falls doch, killt man diese.
Danach startet man den Prozess von Hand im Terminal. In Meinem Fall ist das:
Code: Alles auswählen
$ /usr/bin/uwsgi -s 127.0.0.1:43700 -t 10 -M -p 1 -C -x /home/kev/bottle_site/bottle_uwsgi.conf
*** Starting uWSGI on [Wed Dec 30 13:57:07 2009] ***
your process address space limit is -1 bytes (0 MB)
binding on TCP port: 43700
parsing config file /home/kev/bottle_site/bottle_uwsgi.conf
added /home/kev/bottle_site/ to pythonpath.
interpreter for app 0 initialized.
application 0 (/) ready
setting default application to 0
config file parsed.
request/response buffer (4096 bytes) allocated.
spawned uWSGI master process (pid: 1467)
spawned uWSGI worker 1 (pid: 1468)
[pid: 1468|app: 0|req: 1/1] MEINE_IP () {58 vars in 1005 bytes} [Wed Dec 30 13:57:11 2009] GET / =>
generated 0 bytes in 144 msecs (HTTP/1.1 200) 0 headers in 19 bytes
Ab hier komme ich nicht mehr weiter. Die Applikation selbst funktioniert (über run() ohne uwsgi).
Für uWSGI und Python3 gibt es noch die Seite http://projects.unbit.it/uwsgi/wiki/RunOnPython3k mit Sachen, die man beachten soll. Allerdings betrifft das nur den Charset. Ich nehme doch an, dass ich zumindest kaputten Inhalt bekommen sollte, wenn ich das nicht beachte. In meinem Fall ist es aber gar keiner und ich weiß nicht woran das liegt, da ich mich mit WSGI usw. nicht benügend auskenne.
Ich vermute, dass die Methode __call__ in der Klasse Bottle im Modul bottle.py für die ganzen WSGI Requests letzten endes zuständig ist. Die Methodensignatur deckt sich auch mit der RunOnPython3k Seite von uwsgi.
Aber es kommt anscheinend nichts zurück.
Bin für jeden Tipp sehr dankbar und hoffe mit meiner Beschreibung jedem über die ersten Hürden helfen zu können, der Ähnliches vor hat.
Hier noch einmal zusammenfassend eine Liste mit Quellen/Seiten für weiterführende Informationen mit deren Hilfe ich diese Informationen zusammen getragen habe:
http://projects.unbit.it/uwsgi/wiki
http://projects.unbit.it/uwsgi/wiki/Install
http://projects.unbit.it/uwsgi/wiki/Doc
http://projects.unbit.it/uwsgi/wiki/Example
http://projects.unbit.it/uwsgi/wiki/RunOnPython3k
http://projects.unbit.it/uwsgi/wiki/RunOnCherokee
http://www.cherokee-project.com/doc/cookbook_uwsgi.html
http://bottle.paws.de/page/2009-12-02_release_notes_0.7
http://bottle.paws.de/page/docs#apache-mod_wsgi
http://bottle.paws.de/page/docs#how-default_app-works