I am dealing with an external library that does not handle its resources in a pythonic way. The library is natively a C++ library with a Python wrapper around it. Whenever a library function returns a C++ object, what I actually get is a string handle to it. The object itself persists in memory until I explicitly call a delete() function with that handle as the argument. I tried to introduce my own wrapper around the handle to make sure it is deleted when the wrapper goes out of scope. Something like this:
#import some_module as sm
class MyWrapper(str):
def __new__(*args, **kwargs):
# do something
def __del__(self):
sm.delete(self)
This works most of the time but on script completion I often get an exception that says sm has no attribute delete. It looks like the module object gets destroyed before my wrapper around the handle. Is there a way to make sure my __del__ is called before the module is unloaded?
Interpreter shutdown may clear modules in arbitrary order. Store any required cleanup functions locally in
__del__by binding them as defaults:Since defaults are bound on definition and remain until the function itself is deleted,
_deletewill keep the originalsm.deleteavailable as long as the function/method lives.Note that
__del__may be called at an arbitrary time, including never. It is generally a good idea to use it as a last resort: provide other means to explicitly release the object (e.g. supportwithor a.close()/.delete()method) and write__del__in such a way that it does nothing if the object was released already.