I was hunting down a problem with hamster dialogs. The problem was quite annoying – you open, for example, the overview window. You pick a good range, like 2 years or so that will make it think for a while (oh wow, just checked – i have 6 years of datas now in my install). After that you close the window and would expect it to be gone for good (with all the window.destroy and everything).

Turns out the window still is “somewhere out there” and whenever you make an update, that overview window, although not really accessible from the code anymore, is still listening to the events and doing it’s refreshes.

While tracking down the problem i found objgraph to be an immense help. This handy utility, using graphviz, can generate you a map of objects referencing the one you are trying to get rid of, like this one:

In the image above, all the __self__ backrefs most of the time are harmless, as they will fall off as soon as you have cut off the main variable (you can look at it as a dependency branch). The problem in the case described above was however the leftmost OneWindow instance that had an array of dialogs stored and because of which the object wouldn’t go away.

The utility can do much more, of course.
In the context of pygtk here is the few lines i ended up plugging in while debugging all the windows:

        import gc
        gc.collect()
        import objgraph
        objgraph.show_backrefs(objgraph.by_type('Window'), filename='sample-graph.png', refcounts=True)
        print objgraph.show_growth()

the first two lines import garbage and collect it so we make sure that we are not looking on obsolete links. The fourth line is generating the image that you see above.
And the show_growth is very handy as it shows you the growth of objects counts every time you call it. If an object does not get unreffed properly, there are good chances that it will just keep growing.

About these ads