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-----
|