Hi Pythonistas!
Today I’m sharing a subtle but powerful tip for Python developers. When caching objects, avoid memory leaks by using weakref. Let me show you how regular caching can cause hidden problems and how weakref.WeakValueDictionary solves them beautifully.
The Problem: Hidden References in Caches
In [2]: class User:
...: def __init__(self, name):
...: self.name = name
...:
In [3]: cache = {}
In [4]: u = User("Harry Potter")
In [5]: cache["Harry Potter"] = u
In [6]: print(cache["Harry Potter"].name)
Harry Potter
In [7]: del u
In [8]: print(cache["Harry Potter"].name)
Harry Potter
In [9]: cache
Out[9]: {'Harry Potter': <__main__.User at 0x75505c5cb9a0>}
In [10]:
Even after del u, the object is still alive!
Why? Because cache still holds a strong reference to the object.
This means the object will never be garbage collected, a potential memory leak in long-running programs like web apps or servers.
The Fix: Use weakref.WeakValueDictionary
In [20]: import weakref
In [21]: cache = weakref.WeakValueDictionary()
In [22]: u = User("Harry Potter")
In [23]: cache["Harry Potter"] = u
In [24]: print(cache.get("Harry Potter"))
<__main__.User object at 0x75505c34f2b0>
In [25]: del u
In [26]: print(cache.get("Harry Potter"))
None
In [28]:
Boom! Once the original reference (u) is deleted, the object is garbage collected — and automatically removed from the cache.
Why Use weakref?
- Prevents memory leaks in object caches
- Automatically cleans up unused objects
- Useful for large data, object pools, or expensive resources
Caution
- You must keep at least one strong reference, or the object will vanish!
- Only works with heap-allocated objects (i.e., instances of classes, not int, str, or tuple)
Use weakref.WeakValueDictionary when:
- You're caching objects
- You want automatic memory cleanup
- You’re building tools like ORMs, APIs, or in-memory registries
Stay clean, lean, and memory-efficient.