Hi all
I have a situation where I thought using weakrefs would save me a bit of
effort.
I have a basic publish/subscribe scenario. The publisher maintains a
list of listener objects, and has a method whereby a listener can
subscribe to the list by passing in 'self', whereupon it gets added to
the list.
When the publisher has something to say, it calls a pre-defined method
on each of the listeners. Simple, but it works.
The listeners are fairly transient, so when they go out of scope, I need
to remove them from the list maintained by the publisher. Instead of
keeping track of all of them and removing them explicitly, I thought of
using weakrefs and let them be removed automatically.
It almost works. Here is an example -
import weakref
class A: # the publisher class
def __init__(self):
self.array = []
def add_b(self, b):
self.array.append(weakref.ref(b, self.del_b))
def del_b(self, b):
self.array.remove(b)
def chk_b(self, ref):
for b in self.array:
b().hallo(ref)
class B: # the listener class
def __init__(self, a, name):
self.name = name
a.add_b(self)
def hallo(self, ref):
print(self.name, 'hallo from', ref)
def __del__(self):
print('%s deleted' % self.name)
a = A()
x = B(a, 'test x')
y = B(a, 'test y')
z = B(a, 'test z')
a.chk_b(1)
del x
a.chk_b(2)
del y
a.chk_b(3)
del z
a.chk_b(4)
print(a.array)
The output is as expected -
test x hallo from 1
test y hallo from 1
test z hallo from 1
test x deleted
test y hallo from 2
test z hallo from 2
test y deleted
test z hallo from 3
test z deleted
[]
Then I tried weakref.proxy.
I changed
self.array.append(weakref.ref(b, self.del_b))
to
self.array.append(weakref.proxy(b, self.del_b))
and
b().hallo(ref)
to
b.hallo(ref)
I got the same result.
Then I varied the order of deletion - instead of x, then y, then z, I
tried x, then z, then y.
Now I get the following traceback -
test x hallo from 1
test y hallo from 1
test z hallo from 1
test x deleted
test y hallo from 2
test z hallo from 2
Exception ReferenceError: 'weakly-referenced object no longer exists' in
<bound
method A.del_b of <__main__.A object at 0x00A8A750>> ignored
test z deleted
test y hallo from 3
Traceback (most recent call last):
File "F:\junk\weaklist.py", line 70, in <module>
a.chk_b(3)
File "F:\junk\weaklist.py", line 51, in chk_b
b.hallo(ref)
ReferenceError: weakly-referenced object no longer exists
test y deleted
If I go back to using weakref.ref, but with the new deletion order, it
works.
So now I am confused.
1. Why do I get the traceback?
2. Can I rely on using weakref.ref, or does that also have some problem
that has just not appeared yet?
Any advice will be appreciated.
BTW, I am using python 3.2.2.
Thanks
Frank Millman
--
http://mail.python.org/mailman/listinfo/python-list