Question about weakref

Frank Millman frank at
Wed Jul 4 15:46:46 CEST 2012

Hi all

I have a situation where I thought using weakrefs would save me a bit of 

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):
     def chk_b(self, ref):
         for b in self.array:

class B:  # the listener class
     def __init__(self, a, name): = name
     def hallo(self, ref):
         print(, 'hallo from', ref)
     def __del__(self):
         print('%s deleted' %

a = A()
x = B(a, 'test x')
y = B(a, 'test y')
z = B(a, 'test z')
del x
del y
del z

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))
         self.array.append(weakref.proxy(b, self.del_b))

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 
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\", line 70, in <module>
   File "F:\junk\", line 51, in chk_b
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 

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.


Frank Millman

More information about the Python-list mailing list