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