Flup installieren
Motivation
Im Python-Bereich existieren viele Anwendungen, die die CGI-Schnittstelle unterstützen. FastCGI auf direktem Wege ist eher ungebräuchlich.
Seit einigen Jahren etabliert sich für Python-Anwendungen und -Frameworks der Python Standard WSGI [1], eine Schnittstelle zur Kommunikation zwischen einem Webserver und einer Python-Webanwendung.
Beispielsweise roundup, Django, Trac und die kommende Mailman-Generation WSGI-fähig. Sogar für Zope gibt es mit Repoze eine WSGI-Implementierung.
Direkte Unterstützung für WSGI bieten wir über mod_wsgi, welches leider, wie auch mod_jk Benutzer der Option "eigene httpd.conf" vorbehalten ist, da hierfür der VirtualHost speziell konfiguriert werden muss.
Im Regelfall möchte man vermutlich jedoch nicht unbedingt die Option "eigene httpd.conf" bestellen. Einen Lösungsansatz bietet flup [2], welcher u.a. auch von Trac genutzt wird, um OOTB eine CGI- und FastCGI-Schnittstelle anzubieten. Flup kann also als Adapter zwischen der CGI- oder FastCGI-Schnittstelle des Webservers und der WSGI-Schnittstelle einer Webanwendung fungieren. Aus Performancegründen empfiehlt sich regelmäßig FastCGI. Daneben bietet flup diverse weitere Schnittstellen [3].
Auch der Einsatz von CGI, FastCGI, WSGI*, SCGI* oder AJP* erfordern keinen Root-Server, sondern ist mit Hostsharing-Bordmitteln möglich.
Anmerkung
* Ohne Adapter (etwa FastCGI <-> WSGI) erfordern diese Schnittstellen die Option "eigene httpd.conf". Mit gebuchter Option "eigene httpd.conf" können diese Schnittstellen auf direktem Wege (wie auf einem Root-Server) konfiguriert werden.
Nutzung von flup
flup ist bei HS zentral installiert. Man kann diverse Varianten der WSGIServer-Implementation importieren:
user@hNN:~$ python Python 2.5.2 (r252:60911, Jan 4 2009, 17:40:26) [GCC 4.3.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from flup.server.fcgi import WSGIServer >>> from flup.server.cgi import WSGIServer >>> from flup.server.scgi import WSGIServer >>> from flup.server.ajp import WSGIServer
Wrapper erstellen
Beispiel für roundup
zusammen mit
WSGI Handler
The WSGI handler is quite simple. The following sample code shows how to use it:
from wsgiref.simple_server import make_server # obtain the WSGI request dispatcher from roundup.cgi.wsgi_handler import RequestDispatcher tracker_home = 'demo' app = RequestDispatcher(tracker_home) httpd = make_server('', 8917, app) httpd.serve_forever()
To test the above you should create a demo tracker with python demo.py.
Edit the config.ini to change the web URL to http://localhost:8917/
.
und
aus der flup-Doku
28 fcgi - a FastCGI/WSGI gateway. 29 30 For more information about FastCGI, see <http://www.fastcgi.com/>. 31 32 For more information about the Web Server Gateway Interface, see 33 <http://www.python.org/peps/pep-0333.html>. 34 35 Example usage: 36 37 #!/usr/bin/env python 38 from myapplication import app # Assume app is your WSGI application object 39 from fcgi import WSGIServer 40 WSGIServer(app).run()
kann man einen Wrapper basteln, der
- ein gültiges CGI- oder FastCGI-Skript darstellt
- und einen WSGI-Server für die Applikation implementiert
Wrapper für CGI:
#!/usr/bin/env python import sys sys.path.append("/home/pacs/xyz00/users/USERNAME/roundup/install/lib/python2.5/site-packages") from flup.server.cgi import WSGIServer # obtain the WSGI request dispatcher from roundup.cgi.wsgi_handler import RequestDispatcher tracker_home = '/pfad/zum/tracker/home/verzeichnis' app = RequestDispatcher(tracker_home) WSGIServer(app).run()
Skizze für FastCGI:
#!/usr/bin/env python from fcgi import WSGIServer # hier: fastcgi from myapplication import app # Hier muss ich schauen, # dass ich das app-Objekt meiner Applikation importiert bekomme. # im obigen Fall also app = RequestDispatcher(tracker_home) WSGIServer(app).run()
Für Django läuft die Erstellung eines Wrappers analog. Wichtig ist in jedem Fall ein App-Objekt für die Zielsoftware. Trac bringt freundlicherweise einen fertigen "Stub" mit.
[1] http://www.python.org/dev/peps/pep-0333/
[2] http://trac.saddi.com/flup
[3] http://trac.saddi.com/flup/browser/flup/server
Ganz einfaches Hello World Beispiel
Flup ist auf dem Hostsharing Server bereits für Python2 installiert.
Zunächst legt man das FastCGI-Skript (python.fcgi) an und legt es im fastcgi-ssl Verzeichnis ab und macht es ausführbar:
xyz-doms:~$ cd doms/example.com xyz-doms:~$ export path_to_domain=`pwd` xyz-doms:~$ cat > fastcgi-ssl/python.fcgi <<FINISH #!/usr/bin/env python import os, sys from flup.server.fcgi import WSGIServer os.chdir("$path_to_domain/myproject") sys.path.insert(0, "$path_to_domain/myproject") from myproject import app WSGIServer(app).run() FINISH xyz-doms:~$ chmod a+x fastcgi-ssl/python.fcgi
Nun muss noch die eigentliche App angelegt werden:
xyz-doms:~$ cd doms/example.com xyz-doms:~$ mkdir myproject xyz-doms:~$ cat > myproject/myproject.py <<FINISH def app(environ, start_response): data = b"Hello, World!\n" start_response("200 OK", [ ("Content-Type", "text/plain"), ("Content-Length", str(len(data))) ]) return iter([data]) FINISH
Nun ist die Seite unter www.example.com/fastcgi-bin/python.fcgi erreichbar.
Erweitertes Hello World Beispiel mit Python3 und Flask
Falls man auf ein eigenes Python Virtualenv setzen möchte, weil man z.B. Python3 mit weiteren Paketen nutzen möchte, kann man folgendermaßen vorgehen:
Zunächst wird die Virtualenvumgebung erstellt:
xyz00-doms:~$ virtualenv -p /usr/bin/python3 pyenv Already using interpreter /usr/bin/python3 Using base prefix '/usr' New python executable in pyenv/bin/python3 Also creating executable in pyenv/bin/python Installing setuptools, pkg_resources, pip, wheel...done.
Dann werden die benötigten Bibliotheken in die eben erstellte Virtualenvumgebung installiert.
xyz-doms:~$ source pyenv/bin/activate (pyenv) xyz-doms:~$ pip3 install flask flup ... Successfully installed Jinja2-2.11.2 MarkupSafe-1.1.1 Werkzeug-1.0.1 click-7.1.2 flask-1.1.2 flup-1.0.3 itsdangerous-1.1.0
Nun legt man das FastCGI-Skript (python.fcgi) an und legt es im fastcgi-ssl Verzeichnis ab und macht es ausführbar:
xyz-doms:~$ export pyenv=$HOME/pyenv xyz-doms:~$ cd doms/example.com xyz-doms:~$ export path_to_domain=`pwd` xyz-doms:~$ cat > fastcgi-ssl/python.fcgi <<FINISH #!$pyenv/bin/python import os, sys from flup.server.fcgi import WSGIServer os.chdir("$path_to_domain/myproject") sys.path.insert(0, "$path_to_domain/myproject") from myproject import app WSGIServer(app).run() FINISH xyz-doms:~$ chmod a+x fastcgi-ssl/python.fcgi
Nun muss noch die eigentliche App angelegt werden:
xyz-doms:~$ cd doms/example.com xyz-doms:~$ mkdir myproject xyz-doms:~$ cat > myproject/myproject.py <<FINISH from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "<h1 style='color:blue'>Hello There!</h1>" if __name__ == "__main__": app.run(host='0.0.0.0') FINISH
Nun ist die Seite unter www.example.com/fastcgi-bin/python.fcgi erreichbar.
Hilfreiche Tipps
Seite direkt auf www.example.com verfügbar
Erstmal ist die Seite nur unter www.example.com/fastcgi-bin/python.fcgi erreichbar.
So wird das Projekt unter www.example.com verfügbar gemacht:
Hierfür wird eine .htaccess im entsprechenden Domainverzeichnis angelegt:
xyz-doms:~$ cd doms/example.com xyz-doms:~$ cat > .htaccess <<FINISH RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ /fastcgi-bin/python.fcgi/$1 [QSA,L] FINISH
Nun sollte die Seite unter (www.)example.com erreichbar sein.
Server soll Änderungen in der App übernehmen
Manchmal werden Änderungen in den Quellen nicht übernommen. Dann hilft es den Zeitstempel der Datei python.fcgi mit touch zu aktualisieren:
xyz-doms:~$ touch doms/example.com/fastcgi-ssl/python.fcgi
Alternativ kann der Prozess gestoppt werden:
xyz-doms:~$ ps xaf | grep pyenv | grep -v grep 7195 ? Sl 0:01 | \_ /.../pyenv/bin/python python.fcgi xyz-doms:~$ kill 7195
oder in einer Zeile:
xyz-doms:~$ kill `ps xaf | grep pyenv | grep -v grep | awk '{print $1}'`
Weiterführende Links
http://rephrase.net/days/08/10/roundup-dreamhost
http://old.nabble.com/lighttpd,-fastcgi-and-roundup-td7752461.html
http://wiki.dreamhost.com/index.php/Python_FastCGI#Using_Flup
http://www.domaincamp.de/support/python
http://code.google.com/p/modwsgi/wiki/QuickConfigurationGuide
http://stackoverflow.com/questions/800584/wsgiserver-errors-when-trying-to-run-django-app
http://code.google.com/p/modwsgi/wiki/IntegrationWithTrac