If I am going to implement a safe resource wrapper in Python, do I need to implement the Dispose Pattern like C#?
Here is a demo implementation of what I mean:
class ResourceWrapper:
def __init__(self):
self._python_resource = ... # A Python object that manages some resources.
self._external_resource = _allocate_resource() # A resource handle to an external resource.
self._is_closed = False # Whether the object has been closed.
def __del__(self):
self._close(manual_close=False) # Called by GC.
def close(self):
self._close(manual_close=True) # Called by user to free resource early.
def _close(self, manual_close):
if not self._is_closed: # Don’t want a resource to be closed more than once.
if manual_close:
# Since `_close` is called by user, we can guarantee that `self._python_resource` is still valid, so we
# can close it safely.
self._python_resource.close()
else:
# This means `_close` is called by GC, `self._python_resource` might be already GCed, but we don’t know
# for sure, so we do nothing and rely on GC to free `self._python_resource`.
pass
# GC will not take care of freeing unmanaged resource, so whether manual close or not, we have to close the
# resource to prevent leaking.
_free_resource(self._external_resource)
# Now we mark the object as closed to prevent closing multiple times.
self._is_closed = True
self._python_resource
is a resource wrapper object managed by Python GC, and self._external_resource
is a handle to an external resource that is not managed by Python GC.
I want to ensure both managed and unmanaged resource gets freed if user manual closes the wrapper, and, they also gets freed if the wrapper object gets GCed.