Re: [SQLObject] Problem with circular references
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
From: Dan P. <da...@ag...> - 2006-10-03 16:10:20
|
On Tuesday 03 October 2006 18:17, Oleg Broytmann wrote: > I don't think the problem is in .expireAll(). What is going on, as I > understand, is that .expireAll() clears the cache and as now there are > only weak reference to the row, Python garbage-collects it immediately. > After that Python is free to create another object at the same address. I thought about this in the beginning, but I tried some simple test which was unsuccessful, so I thought it must be something else. The test showed that addresses were not reused: >>> s = {'foo': 1} >>> id(s) -1210595428 >>> del s >>> s = {'bar': 1} >>> id(s) -1210595972 But today I tried the test differently: >>> class Obj(object): ... def __del__(self): ... print "deleted" ... >>> o = Obj() >>> id(o) -1210983732 >>> del o deleted >>> o = Obj() >>> id(o) -1210983636 >>> class A: ... def __del__(self): ... print "deleted" ... >>> a = A() >>> id(a) -1211041652 >>> del a deleted >>> a = A() >>> id(a) -1211041652 So it seems that for objects that are obtained from classes derived from object (strings, dictionaries, Obj(object), ...) it won't reuse the addresses, but for objects that result from old style (pre 2.2) classes it seems it will. So if those objects that are referenced by the weakref are not derived from new style classes, this would explain it indeed. > the solution would be either to check weak references or to hold a real > reference, like this: > > def test_cache(): > setupClass(CacheTest) > s = CacheTest(name='foo') > obj_id = id(s) > s_id = s.id > assert CacheTest.get(s_id) is s > assert not s.sqlmeta.expired > CacheTest.sqlmeta.expireAll() > assert s.sqlmeta.expired > CacheTest.sqlmeta.expireAll() > s1 = CacheTest.get(s_id) > # We should have a new object: > assert id(s1) != obj_id > obj_id2 = id(s1) > CacheTest._connection.expireAll() > s2 = CacheTest.get(s_id) > assert id(s2) != obj_id and id(s2) != obj_id2 > If this test works I think it's a better version of the original one. This test looks fine to me as it shows that the object the cache returns after an expiration is different that the one before even if it has the same id (or at least it would have the same id if the old object would not be kept around by a reference) > (I have removed "del" statments and created s1 and s2 instead of s.) > > If I understand it right, the failure in test_cache() actually shows > that your patch really works and helps to save memory! (-: That thing I already knew without the test ;) -- Dan |