durusmail: quixote-users: Session demo / management with mod_python
Session demo / management with mod_python
ERROR_EMAIL messages have blank subject and message body under SCGI
2003-09-02
ERROR_EMAIL messages have blank subject and message body under SCGI
2003-10-13
2003-10-14
2003-10-14
2003-10-14
Session demo / management with mod_python
mpalmer@sciborg.uwaterloo.ca
2003-08-31
Session management with Quixote and mod_python

Quixote comes with a session demo ready to run in cgi mode. However, there is no
clear description how to do session management when using mod_python.
Here is one way how to get the session demo going with mod_python, making some
simple adjustments in several places. These changes will also let you set up
customized session handling with multiple quixote applications on one machine.

1. I moved session_demo.cgi and session.ptl from quixote/demo/  into a new
directory, which on my machine is named

/MyPy/session_demo

I put an empty file named  __init__.py  into the same directory to make it a
package.


2. I turned session_demo.cgi into a module, saving it as

demo_session.py

I deleted the following lines (toward the end of the file):

enable_ptl()

and:

app = SessionPublisher('quixote.demo.session', session_mgr=session_mgr)
app.read_config("demo.conf")
app.setup_logs()
app.publish_cgi()

since all these things are taken care of in the mod_python handler. As well, I
deleted the corresponding import statements at the top of the file.
The job that remains with session_demo.py is to define the session class, the
session mapping, and the session manager. Quixote very nicely wraps everything
else into the session manager object, so only the latter needs to be exported.
It is placed into the global variable session_mgr, which in turn is picked up by
the mod_python handler.


3. I made some changes to the mod_python_handler.py that comes with Quixote.
These make the handler initialize each new instance of ModPythonPublisher with a
pre-configured session manager, which it expects in the global variable
session_mgr of your session module. The session module is located using a
PythonOption instruction in the httpd.conf file (see below).
The modified source code (saved, on my machine, as module mp_session_handler in
package mylib) is below:

"""quixote.mod_python_handler
$HeadURL: svn://svn/repos/trunk/quixote/mod_python_handler.py $
$Id: mod_python_handler.py 20965 2003-03-05 18:40:37Z akuchlin $

mod_python handler for Quixote.  See the "mod_python configuration"
section of doc/web-server.txt for details.
"""

__revision__ = "$Id: mod_python_handler.py 20965 2003-03-05 18:40:37Z akuchlin
$"

# adapted from Erno Kuusela's quixote_handler.py, 2001/09/19 GPW

#  modified to import an application-specific session manager
# (by the name of session_mgr)
# from an application-specific session module
# as specified in the apache httpd.conf  --- M.P.

import os, sys
from mod_python import apache
from quixote import enable_ptl
from quixote.publish import SessionPublisher, Publisher

enable_ptl()
name2publisher = {}

def handler(req):
    opts = req.get_options()

    try:
        package = opts['quixote-root-namespace']
    except KeyError:
        package = None

    if not package:
        return apache.HTTP_INTERNAL_SERVER_ERROR
    else:
        pub = name2publisher.get(package)
        if pub is None:
            # get the applicable module that contains the
            # pre-configured session manager
            try:
                sess_mod_name = opts['session-module']
                try:
                    sess_mod = __import__(sess_mod_name)
                except ImportError:
                    raise ImportError, __name__ + ".handler can't find module "
+ sess_mod_name
                sessionManager = sess_mod.session_mgr
            except KeyError:
                raise KeyError, 'No PythonOption session-module in httpd.conf
for ' + package
            except AttributeError:
                raise AttributeError, 'module ' + sess_mod_name + ' has no
attribute session_mgr'

            pub = ModPythonPublisher(package, sessionManager)

            try:    # read the application-specific configuration file
                pub.read_config(opts['configuration-file'])
            except KeyError:
                pass
            except IOError:
                pass

            pub.setup_logs()
            name2publisher[package] = pub
        return pub.publish_modpython(req)


class ModPythonPublisher(SessionPublisher):

    def __init__(self, package, session_mgr):
        SessionPublisher.__init__(self, root_namespace=package,
session_mgr=session_mgr, config=None)

    def publish_modpython(self, req):
        """publish_modpython() -> None

        Entry point from mod_python.
        """
        self.publish(apache.CGIStdin(req),
                     apache.CGIStdout(req),
                     sys.stderr,
                     apache.build_cgi_env(req))
        return apache.OK




4. I added the following lines to my httpd.conf file:


    SetHandler python-program

    # use the modified mod_python_handler
    PythonHandler mylib.mp_session_handler

    PythonOption configuration-file /MyPy/session_demo/sdemo.conf
    PythonOption quixote-root-namespace session_demo.session

    # let mp_session_handler import the session manager definition for the demo
    PythonOption session-module demo_session

    PythonInterpreter session_demo
    PythonDebug On

    # prepend our directory to the Python path
    PythonPath "['/MyPy/session_demo']+sys.path"




That's it.
Now, to set up multiple quixote applications on one machine with different
session handling, you just need to modify the 'PythonOption session-module' line
in your httpd.conf file to point it to the application-specific session module
in question.

---------------

Some additional remarks:

1. The Quixote session demo defines a DirMapping class to store the sessions.
This mapping will cache recently accessed sessions. With mod_python, you may
have several independent server processes interacting with successive requests
from the same client. This would lead to the same session being cached multiple
times; moreover, all but one of these caches would then not be current with the
most recent state of the session. If you want to use DirMapping, you should
probably just disable the cache. Alternatively, you might make sure (by editing
httpd.conf) that connections are kept alive for at least as long as the
DirMapping cache - but I don't know whether that's a bulletproof method.

2. The demo also suggests the use of the shelve module from the standard library
for session storage. To make this work, you need to override method
commit_changes in quixote.session.SessionManager (which is normally empty):

    def commit_changes(self, session):
        '''
        when using shelve:
        ensure that the session gets written to disk
        '''
        try:
            self.sessions.close()
        except:
            pass

3. Finally, a hint not directly related to session management:

If you want to have mod_python do 'one-shot' serving of your quixote application
during developent (just as with cgi) to ensure that all your changes show up
immediately, without server restarts, all you need to do is edit your
httpd.conf:

MaxRequestsPerChild 1
KeepAlive Off

Of course, that's not acceptable in production; also, it will hide those errors
that arise only upon repeated execution.

Cheers, Michael





----------------------------------------
This mail sent through www.mywaterloo.ca

reply