[mod_python] Problem keeping persistent object in memory (global)

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




More information about the Mod_python mailing list