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 class HelloResource(resource.Resource): ... reactor.listenTCP(8080, server.Site(HelloResource())) reactor.run()
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 def hello_world(request): ... if __name__ == '__main__': config = Configurator() ... app = config.make_wsgi_app() serve(app, host='0.0.0.0')
In CherryPy, the normal server is cherrypy.engine which is invoked as:
cherrypy.engine.start() cherrypy.engine.block()
cherrypy.engine is actually an instance of cherrypy.process.wspbus.Bus. A simpler alternative to the engine calls is to use:
cherrypy.quickstart(app())
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()) app.run()
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.:
import pesto dispatcher = pesto.dispatcher_app() ... httpd = make_server('', 8080, dispatcher) httpd.serve_forever()
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 main(MyApp())
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!
Nice Post, but why did you leave tornado framework?
Hi Tomasz,
As I wrote in the first post (I did list Tornado there), “I had to draw the line somewhere.” I know it’s somewhat arbitrary, but 12 frameworks is quite a bit already. You (and anyone else) are welcome to add details about your favorite framework in the comments.
Then I will add web2py http://www.web2py.com:
command:
python web2py.py
I then invokes the rocket webserver: https://launchpad.net/rocket
My post does mention Rocket. I didn’t include the command line invocation for web2py because (at least on Debian Linux) it installs itself in the Gnome menu, plus from the command line, it can be invoked directly from the command line, e.g., web2py.
Pingback: Joe Abbate: Python Web Frameworks –... | Python | Syngu
Based on Seth Davis’s web frameworks shootout I’ve compiled number of wrappers to invoke various WSGI servers to serve given WSGI app. See http://hg.zartsoft.ru/web/minimal/file/tip/wsgiserve.py
That looks similar to what Bottle has (starting at the comment “# Server Adapter”).
Thanks for the pointer, gotta add few more adapters.
To invoke Pyramid’s dev server, it’s a bit different:
would like to know more about the strengths/weaknesses of these development resources. For example, one of the things i love about the django dev server is that it “listens” to all the project dependencies and restarts when any file is saved (which has saved me from trying to understand why something I fixed didn’t work and discovering that it’s because the changes weren’t .pyc’d)
Most frameworks and/or servers offer some “reload” capability, usually for use during development, at a minimum over the module files and possibly over the template files, but sometimes this can be extended. Werkzeug for example has an extra_files argument to its run_simple function.
[Quixote](http://quixote.ca) provides an easy way to use some simple servers as well.::
python -m quixote.server.simple_server
python -m quixote.server.medusa_server
python -m quixote.server.twisted_server
python -m quixote.server.fastcgi_server
python -m quixote.server.scgi_server
I guess I should add better support for WSGI.
There’s also a Django app which adds a trunserver command to run dev-mode on top of twisted. Very nice for sites with lots of small files, possibly sufficient for very light “production” – you and a couple of friends/alpha testers. I’m not so fond of the default logging, which apes Apache, and clutters the display much more than the regular dev server.
https://github.com/gregarmer/trunserver
Pingback: Python Web Frameworks – Application Object | Taming Serpents and Pachyderms
Pingback: Database User Interfaces – Pagination | Taming Serpents and Pachyderms
Pingback: ANFSCD: Revisiting the Web Server | Taming Serpents and Pachyderms