I want to use an object's __del__
method to automatically write the object data to either an external database or a local cache (a global dict), depending on certain conditions. A context manager doesn't work for me.
However, this means that, once __del__
is called (because the object has gone out of scope), a new reference to the object may be created in the local cache. Because this sounded like potential trouble, I wrote a simple short test case:
cache = []
class Temp:
def __init__(self) -> None:
self.cache = True
def __del__(self) -> None:
print('Running del')
if self.cache:
cache.append(self)
def main():
temp = Temp()
print(temp.cache)
main()
if cache:
print(cache[0].cache)
When I run this, it outputs:
True
Running del
True
Whereas I expected
True
Running del
True
Running del
I.e. __del__
called twice, once when it originally went out of scope at the end of main
and once at the end of the program, since a new reference was stored in the cache. Why didn't __del__
run twice?
This is implementation specific behavior, see the docs of __del__
. You are performing a "resurrection", i.e. you abort the garbage collection of an object. In older versions of python, this would have easily crashed your interpreter, but since PEP 442 this should mostly work. However, CPython specifically doesn't call the __del__
of a resurrected object on interpreter shutdown.
In general, avoid accessing anything that isn't directly tied to your object in an __del__
method, including for example the global cache
variable. There is no guarantee that it still exists.
For this usecase, use context managers, or since these are apparently not usable for you, atexit
.