[mod_python] Application session

Michael Rasmussen mir at miras.org
Sat Jan 6 21:49:35 EST 2007


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi Graham,

I might have solve my problems. Your article helped a lot.
Read my solution a clarification of my problem below.

On Sat, 6 Jan 2007 11:38:14 +1100
Graham Dumpleton <grahamd at dscpl.com.au> wrote:

>
> You might then perhaps explain better what you are talking about.
>
> In short, any module that is imported within the context of a Python
> interpreter instance is usable by any handler executing within that
> Python interpreter instance in that process. This is totally
> unrelated to
> user sessions created as a result of some form based/login mechanism.
>
> What isn't clear is whether when you say 'sessions' you are talking
> about user sessions or merely concurrent executing request handlers.
>
The picture:

I have an application which provides admin users the ability to add
extensions into the runtime. These extensions must be available to all
users as soon as they are instantiated without the users needs for
restarting their sessions. The extensions must also be persistent in
the runtime until either the application/apache is restarted or they
deactivated by the admin users. Had the application been programmed in
Java - JSP/Servlets, such extensions would have be stored in the
application session: <jsp:useBean id="applicationBean"
class="some.Bean" scope="application" />. This means that for any user
session currently and later on can access the bean and its members. In
Java/JSP you operate with four different kinds of scope: page, request,
session and application. the first three are all related to the same
user session in the said application while the last one is related to
the application instance and the by nature related to all users of the
application. Studying your article proved to me that mod_python does
not provide application scope directly?

My application is running in apache under GNU/Linux so it is restricted
to the problems described in your article - prefork and worker. By the
way does this problem also apply to MPM worker?

What I have found out is this:
I thought I could create a class implementing the singleton pattern and
store an instance of the class to the request object but even if a
directory/virtual host only designates one python handler one cannot
rely on that all instances will share the same python
runtime/pythonHandler due to apache's forking nature so this was a
dead-end.

So my final solution was to create the said singleton class and in this
class save private attributes with instance information of the object
store in dictionaries and then use cPickle to store and load the
object's state. Since I cannot control when an instance of the
singleton class is unloaded from the session I was forced to save the
state of the object every time the object's state change.

If anybody is interested you can find my solution below

"""
IPCop Module Loader.

This module is licensed under GPL and is part of the UI to IPCop.
Read online documentation <http://www.ipcop.org>.

Copyright: 2006, Michael Rasmussen <mir at datanom.net>

Last maintainer: 2006-08-21 18:57 +0200 Michael Rasmussen
<mir at datanom.net>

Previous maintainers:

If you find any bugs or have any comments please send an email to
Michael Rasmussen <mir at datanom.net>
"""

VERSION = "0.1"

import os, sys, new, cPickle, anydbm, tempfile, ModuleImporter

class ModuleLoaderException(Exception):
     def __init__(self, msg):
         self.value = msg

     def __str__(self):
         return repr(self.value)

class ModuleLoader:
     """
         Available modules contains reference to
         registered modules.
         Key: ModuleId
         Item: Reference to a module
     """

     __instance = None

     def __init__(self):
         if ModuleLoader.__instance is None :
             ModuleLoader.__instance = ModuleLoader.__singleton()
         self.__dict__['_ModuleLoader__instance'] =
ModuleLoader.__instance def __getattr__(self, attr):
         return getattr(self.__instance, attr)

     def __setattr__(self, attr, value):
         return setattr(self.__instance, attr, value)

     class __singleton:

         def __init__(self):
             dbmIn = anydbm.open(tempfile.gettempdir() +
		"/ipcop_modules.dbm", "c")
	    try:
                 self.__availableModules =
                     cPickle.loads(dbmIn["availableModules"])
             except KeyError:
                 self.__availableModules = {}
             try:
                 self.__activeModules =
                     cPickle.loads(dbmIn["activeModules"])
             except KeyError:
                 self.__activeModules = {}
             dbmIn.close()

         def getModulesList(self):
             try:
                 return self.__availableModules
             except AttributeError:
                 return {}

         def setModulesList(self, list):
             self.__availableModules = list
             dbmOut = anydbm.open(tempfile.gettempdir() +
                 "/ipcop_modules.dbm", "c")
             dbmOut["availableModules"] =
                 cPickle.dumps(self.getModulesList(), 1)
             dbmOut.close()

         def setAvailableModule(self, name, desc):
             self.__availableModules[name] = desc
             dbmOut = anydbm.open(tempfile.gettempdir() +
                 "/ipcop_modules.dbm", "c")
             dbmOut["availableModules"] =
                 cPickle.dumps(self.getModulesList(), 1)
             dbmOut.close()

         def register(self, module, path = None):
             try:
                 if path != None:
                     if (path.find(".") != -1):
                         raise ModuleLoaderException("Illegal character
in path")
                     if (not path.startswith("/")):
                         if (os.getcwd() != '/'):
                             path = os.getcwd() + "/" + path
                         else:
                             path = "/" + path
                     if (path in sys.path):
                         pass
                     else:
                         sys.path.append(path)
                 mod = ModuleImporter.get_mod(module)
                 try:
                     modules = getattr(mod,"__all__")
                     for m in modules:
                         self.register(module + "." + m)
                 except AttributeError:
                     lastDot = module.rfind(u".")
                     module = module[lastDot + 1:]
                     self.setAvailableModule(module, getattr(mod,
"__name__"))
                     ModuleImporter.del_mod(getattr(mod, "__name__"))
             except Exception, ex:
                 raise ModuleLoaderException("Loading module: %s" % ex)

         def unregister(self, module):
             """ unregister """
             t = self.getModulesList()
             del t[module]
             self.setModulesList(t)
             dbmOut = anydbm.open(tempfile.gettempdir() +
"/ipcop_modules.dbm", "c")
             dbmOut["availableModules"] =
cPickle.dumps(self.getModulesList(), 1)
             dbmOut.close()
             ModuleImporter.del_mod(getattr(module, "__name__"))

- --
Hilsen/Regards
Michael Rasmussen

Get my public GnuPG keys:
michael <at> rasmussen <dot> cc
http://keyserver.veridis.com:11371/pks/lookup?op=get&search=0xD3C9A00E
mir <at> datanom <dot> net
http://keyserver.veridis.com:11371/pks/lookup?op=get&search=0xE501F51C
mir <at> miras <dot> org
http://keyserver.veridis.com:11371/pks/lookup?op=get&search=0xE3E80917
- --------------------------------------------------------------
It's all in the mind, ya know.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQFFoF+/VErYVePoCRcRAtV3AKCiqlVRGu+l8KVno28zxC/6tkl4cgCfQU4L
5Rb3VaXrFtWehT7S5Al+2nk=
=io+9
-----END PGP SIGNATURE-----


More information about the Mod_python mailing list