One of the most frequent tasks of a web developer is running the app while it’s being written. So we’ll begin our examination of Python web frameworks by looking at the development servers provided and how does one run the app.
Django developers are used to invoking
python manage.py runserver
The runserver option runs Django’s development server which is invoked via the run() function in django.core.servers.basehttp. This in turn runs a WSGIServer which is derived from Python’s wsgiref’s simple_server.
Twisted Web has its own server based on its core reactor object. Here’s a simple usage example:
from twisted.web import server, resource
from twisted.internet import reactor
Pyramid uses Paste’s paste.httpserver which in turn is based on Python’s BaseHTTPServer. Sample usage:
from paste.httpserver import serve
from pyramid.config import Configurator
if __name__ == '__main__':
config = Configurator()
app = config.make_wsgi_app()
In CherryPy, the normal server is cherrypy.engine which is invoked as:
cherrypy.engine is actually an instance of cherrypy.process.wspbus.Bus. A simpler alternative to the engine calls is to use:
Under the covers, CherryPy also defines a global server variable that is an instance of Server which implements the HTTP server, with help from cherrypy._cpwsgi_server.CPWSGIServer.
Werkzeug has a built-in server, used as follows:
from werkzeug.serving import run_simple
from myproject import make_app
app = make_app(...)
run_simple('localhost', 8080, app, use_reloader=True)
run_simple() invokes its own (werkzeug.serving) make_server which creates one of three types of XxxWSGIServer’s, which are derived from Python’s BaseHTTPServer.HTTPServer.
When Web2py is invoked, a GUI dialog is shown. The dialog is implemented in gluon.widget and its web2pyDialog.start method creates a main.HttpServer. gluon.main’s HttpServer class uses the Rocket server whose code is in gluon.rocket.
In web.py, to run an application you instantiate a web.application and invoke its run() method, e.g.:
app = web.application(urls, globals())
This eventually runs a BaseHTTPServer.HTTPServer from the Python standard library.
Flask‘s WSGI application class (Flask) has a run() method:
run(host='127.0.0.1', port=5000, debug=None, **options)
This invokes the Werkzeug serving.run_simple function (see above).
WebOb doesn’t offer any server per se, but suggests using Paste’s httpserver.serve or wsgiref.simple_server.
Bottle has a standalone run() function:
run(app=None, server='wsgiref', host='127.0.0.1', port=8080,
interval=1, reloader=False, quiet=False, plugins=None, **kargs)
This runs one of several web servers supported, by default, wsgiref, which uses the wsgiref.simple_server.
Pesto suggests using the Python wsgiref directly, e.g.:
dispatcher = pesto.dispatcher_app()
httpd = make_server('', 8080, dispatcher)
Diva uses Python’s WSGIServer from the standard library to implement its main() and serve() standalone functions. The former can be used as follows:
from diva.core import Application
from diva.server import main
class MyApp(Application): pass
Summary: With the exception of Twisted and CherryPy, all frameworks base their development servers on the standard library’s wsgiref or BaseHTTPServer, Paste or Rocket (which claims to be CherryPy-compatible). Lesson for prospective framework creators: Don’t write your own server. However, you may want to enhance your server with auto-reloading, threading, debugging. etc.
There are two approaches to running the app or server. Django and Web2py don’t want the developer to bother with writing app.run() or similar, the other frameworks expect the programmer to plug the various pieces together.
Best wishes for 2012 to all readers!