[PyQt] Debug potential memory leaks

Andreas Pakulat apaku at gmx.de
Wed Apr 8 22:52:06 BST 2015


Hi,

On Wed, Apr 8, 2015 at 10:42 AM, Andreas Pakulat <apaku at gmx.de> wrote:

> Hi Phil,
>
> On Tue, Apr 7, 2015 at 9:55 PM, Phil Thompson <phil at riverbankcomputing.com
> > wrote:
>
>> On 07/04/2015 8:47 pm, Andreas Pakulat wrote:
>>
>>> Hi,
>>>
>>> I'm having a small 'systray' application that monitors a jenkins service
>>> and it seems there's some kind of memory leak, especially on MacOSX.
>>> After
>>> having it run for a while (with the machine going to sleep now and again)
>>> it starts eating quite some memory - if I understand top/ActivityMonitor
>>> correctly - and amd wondering now how I'd best debug a PyQt application's
>>> memory consumption.
>>>
>>> So what tools do you guys usually use to debug such memory leaks? I've
>>> tried valgrind on Linux but there's no good hint there, possibly also due
>>> to the way Python works.
>>>
>>
>> You could try a debug version of Python that will track objects. If that
>> shows objects are not being collected then it is probably a PyQt problem.
>> Otherwise it might be more likely to be a Qt problem.
>
>
> I'll check that option if I can determine its not my own code hanging on
> to objects it shouldn't hang onto anymore...
>

So, it seems like I'm leaking QAction's and they're not garbage-collected
for quite a while even when they're not connected to anymore anymore. I can
'fix' the problem by setting their parent QObject to None and explicitly
calling gc.collect, without the latter the objgraph module (
http://mg.pov.lt/objgraph.py) shows them as  objects without any references
to them even after another minute of the application running.

Maybe a little background on what the app does helps to understand this a
little better. It polls a jenkins instance for states of the various jobs
and for each job a QAction is created and added to the menu of a QSysTray
object. Each time the data is retrieved all existing QActions are removed
from teh menu via removeAction and the dictionary that kept the instances
is cleared. Then a new set of actions is created and added to the menu for
the possibly-changed set of jobs and their changed icons. The parent object
of the actions is the systray's menu, hence having to set their parent to
None when I want to get rid of them makes sense.

What I find surprising though is that Python's gc does not clean them up
even after a while unless I explicitly call gc.collect. Does someone have
an explanation for this?

Andreas
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20150408/a51417a7/attachment-0001.html>


More information about the PyQt mailing list