Skip to content

Instantly share code, notes, and snippets.

@willstott101
Created August 15, 2022 15:35
Show Gist options
  • Save willstott101/8544a7c966b0788ff4f93da410e9fea7 to your computer and use it in GitHub Desktop.
Save willstott101/8544a7c966b0788ff4f93da410e9fea7 to your computer and use it in GitHub Desktop.
MCVE of how finalizers cannot depend on weak reference state in the presence of circular references.
from weakref import WeakValueDictionary
import gc
objs = WeakValueDictionary()
class Registered:
def __init__(self):
objs[id(self)] = self
def __del__(self):
del objs[id(self)]
class Simple(Registered):
pass
class Circular(Registered):
def __init__(self):
super().__init__()
# create a circular reference
def test():
print(self)
self._test_fn = test
def test_simple():
gc.disable()
local_objs = [Simple() for a in range(10)]
assert len(objs) == 10
local_objs = []
assert len(objs) == 0
def test_circular():
"""
This raises because the object is not longer in "objs" by the time the object's
__del__ is called - but this is only the case when there are circular references.
"""
gc.disable()
local_objs = [Circular() for a in range(10)]
assert len(objs) == 10
local_objs = []
assert len(objs) == 10
gc.collect()
assert len(objs) == 0
if __name__ == "__main__":
test_simple()
test_circular()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment