Python

Fix Cache Memory Leaks with weakref

Learn how Python's weakref.WeakValueDictionary prevents memory leaks in caches by automatically cleaning up entries when objects are no longer needed elsewhere.

August 2026 4 min read 12 views 0 hearts

Python's weakref for Caches Without Leaks

You've built a cache in Python. You're proud of it. But then you notice something odd — your program's memory keeps growing, even when it shouldn't. The culprit? Strong references in your cache that prevent objects from being garbage collected.

Let me show you how weakref saves the day, with real examples you can use today.

The Cache Problem

Imagine you're building a web scraper at PythonSkillset that processes thousands of images. You cache expensive results to avoid recalculating:

class ImageProcessor:
    def __init__(self):
        self.cache = {}  # This holds strong references

    def process(self, url):
        if url in self.cache:
            return self.cache[url]

        result = expensive_processing(url)
        self.cache[url] = result  # Strong reference keeps result alive
        return result

Looks innocent, right? But every processed result stays in memory forever, even when nothing else needs it. That's a memory leak.

Enter weakref

weakref creates references that don't prevent garbage collection. The magic happens when an object has only weak references left — Python's garbage collector will clean it up.

import weakref

class ImageProcessor:
    def __init__(self):
        self.cache = weakref.WeakValueDictionary()  # No more leaks!

    def process(self, url):
        if url in self.cache:
            return self.cache[url]

        result = expensive_processing(url)
        self.cache[url] = result  # Object can still be garbage collected
        return result

When Objects Disappear

Here's the trick — if nothing else holds a strong reference to your cached object, weakref.WeakValueDictionary automatically removes that entry when the object is collected. No manual cleanup needed.

class ImageData:
    def __init__(self, url):
        self.url = url
        print(f"Loading {url}")

    def __del__(self):
        print(f"Unloading {self.url}")

cache = weakref.WeakValueDictionary()

img = ImageData("photo.jpg")
cache["photo"] = img

print(cache.get("photo"))  # Works fine

del img  # Remove strong reference
print(cache.get("photo"))  # Returns None — object was cleaned up

Real-World Use at PythonSkillset

At PythonSkillset, we use this pattern for: - Database query caches — When a user session ends, all their cached queries are auto-cleaned - API response caches — Temporary responses that expire when the session object goes away - Worker task results — Results that should disappear when worker processes restart

The WeakValueDictionary Pattern

This is your go-to tool for caches:

import weakref

class TaskCache:
    def __init__(self):
        self._cache = weakref.WeakValueDictionary()

    def get_or_compute(self, task_id, compute_func):
        result = self._cache.get(task_id)
        if result is None:
            result = compute_func()
            self._cache[task_id] = result
        return result

What About Simple Caches?

For simple value caches (strings, numbers, tuples), weakref won't help much — those are immutable and get copied anyway. But for large objects like database records, image data, or API responses, it's a lifesaver.

A Warning

Don't use WeakValueDictionary when you need guaranteed cache persistence. If your application holds no other references to cached objects, they'll vanish. That's the feature, not a bug — but it can surprise you.

The Bottom Line

Memory leaks in Python caches are a real problem, but weakref. WeakValueDictionary gives you automatic memory management without complex cleanup code. Your cache stays lean, your objects get collected when they should, and you stop chasing phantom memory growth.

Try it next time you build a cache that holds large objects. Your future self will thank you when the memory graph stays flat during long Python sessions.

Comments

Questions, corrections, and tips stay visible for everyone reading this page.

0 in thread

Join the discussion

Shown next to your comment.

Up to 4,000 characters

No comments yet

Be the first to leave a note — it helps the next reader.