Contact: fumanchu@aminus.org

Log in as guest/misc to create tickets

How to set up mod_python for use as a WSGI server

The following now works using Apache2, with mpm_winnt and prefork! Other versions and MPM's may give radically different results. If you've got a little time and experience, please try this latest version with prefork on Linux, and any other Multi-Processing Modules you favor.

The mod_python gateway depends upon wsgiref. Get wsgiref from svn://svn.eby-sarna.com/svnroot/wsgiref/src/wsgiref.

Since changeset [39] on Feb 9, 2006, this module no longer depends upon wsgiref.

Grab source:modpython_gateway.py from this site and save it in site-packages, or somewhere else on your Python path. Then add the following to your Apache httpd.conf:

<Location /myapp>
    SetHandler python-program    
    PythonHandler modpython_gateway::handler
    PythonOption wsgi.startup myapp.cherrypy::startapp

    # This is CP 3.0 beta 2 syntax:
    PythonOption wsgi.application cherrypy::tree
    PythonOption wsgi.cleanup cherrypy::engine.stop

    # This is CP 2.2 syntax:
    PythonOption wsgi.application cherrypy._cpwsgi::wsgiApp
    PythonOption wsgi.cleanup cherrypy::server.stop
    
    AuthType Basic
    AuthName "MyApp"
    AuthUserFile D:\htdocs\myapp\passwords
    Require user admin guest

</Location>

myapp.cherrypy refers to a hypothetical myapp/cherrypy.py module that sets up cherrypy and your application. If you provide a function after the "::" (you don't have to), it will be called. Here's a sample script for CP 3.0 beta 2:

import cherrypy

class HelloWorld:
    def index(self):
        return "Hello world!"
    index.exposed = True

cherrypy.tree.mount(HelloWorld())
cherrypy.config.update({"environment": "production"})
cherrypy.engine.start(blocking=False)

Here's the equivalent for CP 2.2:

import cherrypy

class HelloWorld:
    def index(self):
        return "Hello world!"
    index.exposed = True

cherrypy.root = HelloWorld()
cherrypy.config.update({"server.environment": "production",
                        "server.protocolVersion": "HTTP/1.1"})
cherrypy.server.start(initOnly=True, serverClass=None)

Notice that, since we are using Apache to serve our requests, we can tell CherryPy to run in full HTTP/1.1 mode. The HTTP server provided in CherryPy 2.2 was not fully HTTP/1.1 compliant.

SCRIPT_NAME and WSGI

Some WSGI implementations require that the SCRIPT_NAME be equal to the "mount point" of the application. If you're using one of them, the SCRIPT_NAME which Apache invents is probably not going to be accurate. You can now (Feb 2006) manually set the SCRIPT_NAME environ value with a PythonOption:

    PythonOption SCRIPT_NAME /myapp

This will make all WSGI requests use a SCRIPT_NAME of "/myapp"; PATH_INFO will be set to the remainder of the URL.

Init (startup) functions

You can tell modpython_gateway to call a function on the first request with a PythonOption:

    PythonOption wsgi.startup myapp.cherrypy::startapp

Shutdown (cleanup) functions

Recent versions of mod_python include an easy way to declare functions that should be run when Apache exits. You can tell modpython_gateway to run functions at process shutdown with a PythonOption:

    PythonOption wsgi.cleanup cherrypy::engine.stop

Note that the function will be called once per process or thread. If you run 10 threads, it will be called 10 times on Apache shutdown.