As per Python's data model doc:
Objects are never explicitly destroyed; however, when they become unreachable they may be garbage-collected. An implementation is allowed to postpone garbage collection or omit it altogether...
...
Some objects contain references to “external” resources such as open files or windows. It is understood that these resources are freed when the object is garbage-collected, but since garbage collection is not guaranteed to happen, such objects also provide an explicit way to release the external resource, usually a close() method. Programs are strongly recommended to explicitly close such objects. The try…finally
statement and the with
statement provide convenient ways to do this.
So even if in most cases __del__
method of an object is being called by GC, it is not guaranteed. with
statement (from PEP 343) on the other hand guarantees that if __enter__
method of the object succeeded, then __exit__
method will be called at the end of the statement, both in case of normal execution and in case of exception. (More detailed in this question)
An example could be as below, with the usage of "object-closing" context manager from PEP 343 examples, and a wrapper class with close
method which calls native object's destructor:
class NativeObjectWrapper(object):
def __init__(self):
self.nativeObject = nativeLib.CreateInstance()
def close(self):
nativeLib.DestructorFunction(self.nativeObject)
class closing(object):
def __init__(self, obj):
self.obj = obj
def __enter__(self):
return self.obj
def __exit__(self, *exc_info):
try:
close_it = self.obj.close
except AttributeError:
pass
else:
close_it()
#example of usage
with closing(NativeObjectWrapper()) as objectWrapper:
... #some usage of native wrapper