Graham Dumpleton
grahamd at dscpl.com.au
Tue Jun 7 18:02:13 EDT 2005
Whoops. I made a mistake in the code I suggested. Should be: if not globals().has_key("mysitepool"): global mysitepool mysitepool = Pool(Constructor(Site), apache.mpm_query(6)) Ie., has_key() and not has_attr(). Since there is no such thing has "has_attr()", that might be contributing. Sorry. :-( Graham On 08/06/2005, at 12:47 AM, Sébastien Arnaud wrote: > Thank you Graham for the details on the proper use and issues with > using a singleton. > > I have modified my code and it seems that now the object mysitepool is > staying in memory yeah! > > The only other issue is that it seems the Site object I am inserting > in the Pool is getting initialized every-time... It is like the > Queueing mechanism is not working properly and initializing using the > Contructor every-time. > > I am using the pool.py written by Andy dustman > (http://dustman.net/andy/python/), and basically the mysitepool is now > being initialized as shown below. What I am noticing is that the Site > objects which are created in the Pool (basically in the Queue) are > initialized each time you call mysitepool.get(). The behavior I am > looking for is to keep all X Site objects in the Pool to stay in > memory. FYI the Site object initialize a connection to the DB among > other things, so it is critical that it is initialized and destroyed > cleanly. > > Thanks for sharing your wisdom once more ;) > > Sébastien > > handler.py (the one that mod_python points to via PythonHandler in the > .htaccess) > ---------- > from mod_python import apache > from heracles.mysitepool import mysitepool > > def handler(req): > """ > Standard mod_python handler code for Heracles Web Application > Framework > """ > mySite = mysitepool.get() > return mySite(req) > mysitepool.put(mySite) > > mysitepool.py > ------------- > > from mod_python import apache > from heracles.pool import Pool, Constructor > from heracles.site import Site > > if not globals().has_attr("mysitepool"): > global mysitepool > mysitepool = Pool(Constructor(Site), apache.mpm_query(6)) > > pool.py > ------- > # Credits: http://dustman.net/andy/python/ > > from Queue import Queue, Full, Empty > > class Pool(Queue): > """Manage a fixed-size pool of reusable, identical objects.""" > def __init__(self, constructor, poolsize=5): > Queue.__init__(self, poolsize) > self.constructor = constructor > def get(self, block=1): > """Get an object from the pool or a new one if empty.""" > try: > return self.empty() and self.constructor() or > Queue.get(self, block) > except Empty: > return self.constructor() > def put(self, obj, block=1): > """Put an object into the pool if it is not full. The caller > must > not use the object after this.""" > try: > return self.full() and None or Queue.put(self, obj, block) > except Full: > pass > > class Constructor: > """Returns a constructor that returns apply(function, args, kwargs) > when called.""" > def __init__(self, function, *args, **kwargs): > self.f = function > self.args = args > self.kwargs = kwargs > def __call__(self): > return apply(self.f, self.args, self.kwargs) > > > > > On Jun 6, 2005, at 5:08 PM, Graham Dumpleton wrote: > >> On 07/06/2005, at 3:02 AM, Huzaifa Tapal wrote: >> >> >>> One option that I use is to create a singleton in the module that I >>> want to be global at the first import of that module. So lets take >>> your mySitePool module for example: >>> >>> class mySitePool: >>> def __init__(self): >>> ' suite >>> >>> .... >>> >>> global mysitepool >>> mysitepool = mySitePool() >>> >> >> Using singleton approach as described will help, now for some really >> obscure >> stuff in case later on you find other strange problems. >> >> First is that if auto reloading of modules is on and the singleton is >> stored >> in a module which at any time might get reloaded because the file is >> changed, >> the act of reloading will replace the singleton object, resetting it >> in the >> process. >> >> This means that the previously created pool object will become >> inaccessible >> and potentially resources it uses in the way of database connections >> might >> not get shutdown properly if that required an explicit step not >> performed by >> normal Python object deletion. >> >> At the same time, a new pool object will be created and perhaps >> another set >> of database connections. If old ones aren't cleaned up in the >> inaccessible >> pool and new ones are created due to reloads, you might end up with >> too many >> connections and not be able to create any more. >> >> To make the code durable and resistant to reloads, intended or not, >> it is >> useful to write code as: >> >> if not globals().has_attr("mysitepool"): >> mysitepool = mySitePool() >> >> What happens is that reload occurs on top of the existing module. By >> seeing >> if the pool object already exists in globals, you simply avoid >> creating it a >> second time. >> >> Also note that there are some threading issues in mod_python as well, >> and >> if you don't do this fiddle but module reloading is turned off, you >> can still >> have a problem. This is because the threading issues can result in a >> module >> being loaded twice by mistake, as if a reload had occurred. >> >> For this, see patches at: >> >> http://www.dscpl.com.au/projects/vampire/patches.html >> >> Graham >> >> >
|