Path: csiph.com!usenet.pasdenom.info!gegeweb.42!gegeweb.eu!nntpfeed.proxad.net!proxad.net!feeder1-2.proxad.net!usenet-fr.net!nerim.net!novso.com!newsfeed.xs4all.nl!newsfeed5.news.xs4all.nl!xs4all!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'exception': 0.03; 'output': 0.04; 'ignored': 0.05; 'say,': 0.05; 'objects,': 0.07; 'subject:Question': 0.07; 'works.': 0.07; 'python': 0.09; "'test": 0.09; '51,': 0.09; 'deletion': 0.09; 'name):': 0.09; 'received:80.91': 0.09; 'received:80.91.229': 0.09; 'received:gmane.org': 0.09; 'received:list': 0.09; 'def': 0.10; 'passing': 0.15; 'result.': 0.15; '70,': 0.16; 'a()': 0.16; 'b):': 0.16; "deleted'": 0.16; 'explicitly,': 0.16; 'message- id:@dough.gmane.org': 0.16; 'received:80.91.229.3': 0.16; 'received:plane.gmane.org': 0.16; 'scope,': 0.16; 'weakref': 0.16; 'exists': 0.17; 'bit': 0.21; 'import': 0.21; 'fairly': 0.21; 'effort.': 0.22; 'example': 0.23; 'tried': 0.25; 'header:User- Agent:1': 0.26; 'skip:" 20': 0.26; 'appreciated.': 0.26; '(most': 0.27; 'header:X-Complaints-To:1': 0.28; 'skip:_ 10': 0.29; 'class': 0.29; "skip:' 10": 0.30; 'basic': 0.30; 'gets': 0.32; 'file': 0.32; 'skip:s 30': 0.33; 'maintained': 0.33; 'maintains': 0.33; 'traceback': 0.33; 'problem': 0.33; 'to:addr:python-list': 0.33; 'changed': 0.34; 'thanks': 0.34; 'list': 0.35; 'expected': 0.35; 'something': 0.35; 'list.': 0.35; 'received:org': 0.36; 'but': 0.36; 'method': 0.36; 'test': 0.36; 'does': 0.37; 'received:co.za': 0.37; 'received:za': 0.37; 'why': 0.37; 'object': 0.38; 'some': 0.38; 'advice': 0.39; 'instead': 0.39; 'to:addr:python.org': 0.39; 'where': 0.40; 'header:Received:5': 0.40; 'remove': 0.61; 'save': 0.61; 'back': 0.62; 'situation': 0.62; 'here': 0.65; 'received:41': 0.73; 'frank': 0.75; 'listener': 0.84; 'yet?': 0.84; 'whereby': 0.91 X-Injected-Via-Gmane: http://gmane.org/ To: python-list@python.org From: Frank Millman Subject: Question about weakref Date: Wed, 04 Jul 2012 15:46:46 +0200 Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Gmane-NNTP-Posting-Host: 41-133-115-137.dsl.mweb.co.za User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:12.0) Gecko/20120428 Thunderbird/12.0.1 X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 123 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1341409625 news.xs4all.nl 6889 [2001:888:2000:d::a6]:44590 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:24861 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 > ignored test z deleted test y hallo from 3 Traceback (most recent call last): File "F:\junk\weaklist.py", line 70, in 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