Jump to content
  • Advertisement
Sign in to follow this  
Ostsol

Does Python have some sort of "kill all"?

This topic is 4916 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Consider the following:
from TestMod import Base

class Another:
	def __init__ (self):
		print "Initializing Another"
		self.Funky = None
	def __del__ (self):
		self.Funky = None
		print "Finalizing Another"

class Derived (Base):
	def __init__ (self):
		Base.__init__ (self)
		print "Initializing Derived"
		self.another = Another ()
		self.another.Funky = self.Func
	def __del__ (self):
		self.another = None
		print "Finalizing Derived"
	def Func (self):
		print "Funky!"



Base is a C++ class imported into Python via Boost. When Derived gives Another a reference to it Func, it also provides a reference to itself. As a result, when I destroy the reference to Derived in C++, the destructor is not called because there is still one reference remaining: in Another. Both reference each other and there are no other references beyond those. When I call Py_Finalize, Base's destructor is not being called. Is there a way to simply tell Python to clear all references and destroy all objects, calling their destructors? Right now, I have to clear all the references manually.
from TestMod import Base

class Another:
	def __init__ (self):
		print "Initializing Another"
		self.Funky = None
	def __del__ (self):
		self.Funky = None
		print "Finalizing Another"

class Derived (Base):
	def __init__ (self):
		Base.__init__ (self)
		print "Initializing Derived"
		self.another = Another ()
		self.another.Funky = self.Func
	def __del__ (self):
		self.Destroy ()
		print "Finalizing Derived"
	def Destroy (self):
		self.another = None
	def Func (self):
		print "Funky!"


I call the Destroy function in Derived before I delete its C++ reference. This will guarantee that the reference to Another is deleted and its destructor called. However, if there was a similar case with Another (where there was a reference to it an an object that contained a reference back to Another), it would also have to have a Destroy function and Derived would have to call it. I don't know whether or not this would be a problem for straight Python code. I don't know if Python full manages its memory and destroys all objects created. What I do know is that Py_Finalize isn't calling C++ destructors, which can lead to other issues. My own solution isn't -too- much trouble, but I'd like to know if there is something I've missed. Is there, for example, a function in Python's C-API to destroy everything and ensure destructors are properly called?

Share this post


Link to post
Share on other sites
Advertisement
IIRC, a latter release of Python addressed this issue automatically ("mark and sweep"?). What version are you using?

Share this post


Link to post
Share on other sites
Reading the documentation for the gc module should answer a number of your questions.

Quote:
When Derived gives Another a reference to it Func, it also provides a reference to itself. As a result, when I destroy the reference to Derived in C++, the destructor is not called because there is still one reference remaining: in Another. Both reference each other and there are no other references beyond those.


Python's garbage collector cannot reclaim objects which are in a reference cycle and have a destructor (__del__) : it cannot know which one to destroy first, since the destructor might actually rely on the referenced object to be valid. Such objects get listed in gc.garbage, where you are free to manually fix the cycle. The mutual reference problem can be solved with the weakref module.

Quote:
When I call Py_Finalize, Base's destructor is not being called.


Remember that you need virtual destructors.

Quote:
I don't know whether or not this would be a problem for straight Python code. I don't know if Python full manages its memory and destroys all objects created.


The problem is the same in pure Python. Resources might not be released properly. Only process memory and maybe file descriptors, are automatically cleaned up by the OS. Your example is typical. Use a weakref to point to Func.

Quote:
Is there, for example, a function in Python's C-API to destroy everything and ensure destructors are properly called?


None that I know of. Again, see the gc module. The globals() built-in function might also prove useful to get the list of variables known to the interpreter.

Share this post


Link to post
Share on other sites
Hmm. . . I thought this might be the case. I'll take a look at those modules you mentioned. Thanks for the suggestions.

I guess one other thing I could do is create some fairly robust base-classes to handle the reference management for the basic properties such that further extensions don't have to worry about it.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!