[PyQt] Garbage collection, signals to partial functions
Phil Thompson
phil at riverbankcomputing.com
Tue Nov 17 16:38:29 GMT 2009
On Tue, 17 Nov 2009 17:31:29 +0100, Martin Teichmann
<martin.teichmann at mbi-berlin.de> wrote:
> Hi List,
>
> already recently, I reported a problem with
> partial functions as slots not being correctly
> garbage collected. As Phil noted, this was
> fixed in recent snapshots. But since my
> code still wouldn't run properly, I investigated
> a bit more and wrote the following new test case,
> where still the objects are not garbage collected,
> although they should be.
>
> This time I tested with latest snapshot
> (4.6.2-snapshot-20091115 and 4.9.2-snapshot-20091115)
>
> Greetings
>
> Martin
>
> Here we go:
>
> --------------------- snip --------------------------
> import gc
> from PyQt4 import QtCore
> from weakref import ref
> from functools import partial
> import sys
>
> class A(QtCore.QObject):
> def f(self, x):
> print x
>
> # make 2 objects of A
> b = A()
> a = A(b)
> # last line is the important difference to
> # previously reported problems. b is now parent of a.
>
> # connect a signal to a partial function
> f = b.f
> p = partial(f, 3)
> a.connect(a, QtCore.SIGNAL("a"), p)
> wf = ref(f)
> wp = ref(p)
> f = None
> p = None
>
> # kill all references
> wa = ref(a)
> wb = ref(b)
> a = None
> b = None
>
> # but they're still here!
> # (following line prints four objects, but should print four Nones)
> print wa(), wb(), wp(), wf()
>
> # OK, let's garbage collect
> gc.collect()
>
> # still everything there (again, not a single None)
> print wa(), wb(), wp(), wf()
>
> # that's the bug: still one reference, but no referrer
> # (the line prints 1 [], getrefcount always gives 1 to high)
> if wp() is not None:
> print sys.getrefcount(wp()) - 1, gc.get_referrers(wp())
>
> # assert that everything is gone
> assert wa() is None
> assert wb() is None
> assert wp() is None
> assert wf() is None
The proxies that wrap Python callables don't get deleted until the event
loop is run. I'd change your code to start a timer, enter the event loop,
and check the references when the timer times out.
Phil
More information about the PyQt
mailing list