Sign in to follow this  
Black Knight

Python Event class and memory leak

Recommended Posts

Black Knight    769
Hi guys,I am pretty new to python and I have a problem that is bugging me.The following code is a small application that replicates the issue which happens in a larger program.Here is the code :

import gc

class Event:
	def __init__(self, name):
		self.targets = set()
		self.__name__ = name
   
	def __repr__(self):
		return 'event ' + self.__name__
   
	def __call__(self, *a, **kw):
		for f in self.targets: 
			f(*a, **kw)
   
	def __iadd__(self, f):
		self.targets.add(f)
		return self
   
	def __isub__(self, f):
		while f in self.targets: self.targets.remove(f)
		return self
		

		
class GUIObject():
	def __init__(self):
		self.OnClicked = Event('OnClicked')
	

class Map():
	def __init__(self):
		self.button = GUIObject()
		self.button.OnClicked += self.onButtonClicked
	
	def onButtonClicked(self):
		pass

class Game():
	def __init__(self):
		self.map = Map()
		
		
		self.map = Map()
		
		
	
		


	
gc.set_debug(gc.DEBUG_LEAK)


game = Game()


print gc.collect()

print gc.garbage



When I run this program I get the following output.
gc: collectable <dict 022BAC00>
gc: collectable <Map instance at 022C0E90>
gc: collectable <dict 022C1150>
gc: collectable <GUIObject instance at 022C0EB8>
gc: collectable <dict 022C11E0>
gc: collectable <Event instance at 022C0EE0>
gc: collectable <set 01E74D50>
gc: collectable <instancemethod 022B7800>
8
[{'button': <__main__.GUIObject instance at 0x022C0EB8>}, <__main__.Map instance
 at 0x022C0E90>, {'OnClicked': event OnClicked}, <__main__.GUIObject instance at
 0x022C0EB8>, {'__name__': 'OnClicked', 'targets': set([<bound method Map.onButt
onClicked of <__main__.Map instance at 0x022C0E90>>])}, event OnClicked, set([<b
ound method Map.onButtonClicked of <__main__.Map instance at 0x022C0E90>>]), <bo
und method Map.onButtonClicked of <__main__.Map instance at 0x022C0E90>>]



So does this mean I have a memory leak in this code since the gc.garbage list has all those elements.If there is a memory leak is it caused by a circular reference?

Share this post


Link to post
Share on other sites
AndrewBC    280
From the python docs:
Quote:
gc.collect([generation])
With no arguments, run a full collection.


So yeah, when you're printing all the information and you just garbage collected everything, you'll get a full list.

When I ran it without the gc.collect(), I get this:
Quote:

[]
gc: collectable <dict 0149BED0>
gc: collectable <Map instance at 014A2080>
gc: collectable <dict 0149BB70>
gc: collectable <GUIObject instance at 014A20A8>
gc: collectable <dict 0149BD20>
gc: collectable <Event instance at 014A20D0>
gc: collectable <set 012E8D50>
gc: collectable <instancemethod 014963C8>


Which is what you would expect since there's no reason to be garbage at the time of the print, and then everything is collected as the program ends.

Furthermore, there aren't any cyclic references that I can see, which is usually why something would be uncollectable. However, if there is something I'm missing, pay attention to this info from the python docs under gc.garbage...

Quote:

Objects that have __del__() methods and are part of a reference cycle cause the entire reference cycle to be uncollectable, including objects not necessarily in the cycle but reachable only from it. Python doesn’t collect such cycles automatically because, in general, it isn’t possible for Python to guess a safe order in which to run the __del__() methods. If you know a safe order, you can force the issue by examining the garbage list, and explicitly breaking cycles due to your objects within the list. Note that these objects are kept alive even so by virtue of being in the garbage list, so they should be removed from garbage too. For example, after breaking cycles, do del gc.garbage[:] to empty the list. It’s generally better to avoid the issue by not creating cycles containing objects with __del__() methods, and garbage can be examined in that case to verify that no such cycles are being created.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this