Graham Dumpleton
grahamd at dscpl.com.au
Sun Jan 7 00:46:13 EST 2007
Have forwarded this back to the list. Please keep followups there. Depending on what you are doing, you might want to look at memcached for Python as a way of sharing memory between Apache child processes. Alternatively, look at XML-RPC as a way to connect to a long lived back end process which contains the true application. For even more complicated systems, can also suggest messaging system based solutions for communicating with a back end system. These have the benefit of not requiring a separate socket connection for each request like XML-RPC does. Down the track, if interested in these, let me know. Graham On 07/01/2007, at 1:49 PM, Michael Rasmussen wrote: > -----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-----
|