Fundamentals 6 min read

Handling Circular References and Memory Leaks in Python with weakref and gc Modules

This article explains how circular references cause memory leaks in Python, describes the role of reference counting and the cyclic garbage collector, and provides practical examples using the weakref and gc modules to create weak references, detect, and manually manage cyclic garbage.

Test Development Learning Exchange
Test Development Learning Exchange
Test Development Learning Exchange
Handling Circular References and Memory Leaks in Python with weakref and gc Modules

In Python, circular references occur when two or more objects reference each other, forming a loop that prevents the reference‑counting garbage collector from reclaiming the memory, which can lead to memory leaks.

Python mitigates this with a cyclic garbage collector and supports weak references, which do not increase an object's reference count and therefore allow the object to be collected even when other references exist.

1. Create a weak reference using the weakref module:

import weakref
class MyClass:
    pass
obj = MyClass()
ref = weakref.ref(obj)  # create weak reference
print(ref())  # -> <__main__.MyClass object at 0x...>
# delete the strong reference
del obj
print(ref())  # -> None (object has been collected)

2. Use a weak‑reference dictionary:

import weakref
cache = weakref.WeakValueDictionary()
class MyClass:
    def __init__(self, key):
        self.key = key
obj1 = MyClass("obj1")
obj2 = MyClass("obj2")
cache[obj1.key] = obj1
cache[obj2.key] = obj2
print(cache.get("obj1"))  # -> <__main__.MyClass object at 0x...>
# delete a strong reference
del obj1
print(cache.get("obj1"))  # -> None

3. Manually trigger garbage collection with the gc module:

import gc
class MyClass:
    def __init__(self):
        self.other = None
obj1 = MyClass()
obj2 = MyClass()
obj1.other = obj2
obj2.other = obj1
# force collection
gc.collect()
print(gc.get_referents(obj1))  # -> []
print(gc.get_referents(obj2))  # -> []

4. Find cyclic references using gc :

import gc
class MyClass:
    pass
obj1 = MyClass()
obj2 = MyClass()
obj1.other = obj2
obj2.other = obj1
gc.collect()
cycle = gc.garbage
for obj in cycle:
    print(obj)

5. Disable automatic garbage collection:

import gc
class MyClass:
    pass
obj1 = MyClass()
obj2 = MyClass()
obj1.other = obj2
obj2.other = obj1
gc.disable()
# remove strong references
del obj1
del obj2
gc.collect()
print(gc.get_referents(obj1))  # -> []
print(gc.get_referents(obj2))  # -> []

6. Set debugging flags for gc :

import gc
gc.set_debug(gc.DEBUG_LEAK)
# run code that may create cycles
gc.collect()
print(gc.garbage)

7. Manually clear references:

import gc
class MyClass:
    pass
obj1 = MyClass()
obj2 = MyClass()
obj1.other = obj2
obj2.other = obj1
gc.collect()
gc.collect()
print(gc.get_referents(obj1))  # -> []
print(gc.get_referents(obj2))  # -> []

8. Adjust garbage‑collection thresholds:

import gc
gc.set_threshold(5)
# run code that may create cycles
gc.collect()

9. Perform generational collection:

import gc
class MyClass:
    pass
obj1 = MyClass()
obj2 = MyClass()
obj1.other = obj2
obj2.other = obj1
gc.collect(2)  # collect up to generation 2
print(gc.get_referents(obj1))  # -> []
print(gc.get_referents(obj2))  # -> []

10. Change the collection threshold and run collection:

import gc
class MyClass:
    pass
obj1 = MyClass()
obj2 = MyClass()
obj1.other = obj2
obj2.other = obj1
gc.set_threshold(10)
# run code that may create cycles
gc.collect()
print(gc.get_referents(obj1))  # -> []
print(gc.get_referents(obj2))  # -> []

These examples demonstrate how to use weak references and Python's garbage‑collection facilities to detect and break circular references, preventing memory leaks and ensuring objects are properly reclaimed.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

memory-managementPythonGarbage CollectionCircular Referencesweak references
Test Development Learning Exchange
Written by

Test Development Learning Exchange

Test Development Learning Exchange

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.