Created
August 15, 2022 15:35
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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