New

Experience Smart HR with Horilla Mobile App

Google Play Store Google Play Store
Home / Blogs

Overview of Monkey Patching in Python

Python
·

July 18, 2025

overview-of-monkey-patching-in-python

In Python’s dynamic world, few features are as intriguing, or controversial, as monkey patching. It’s a technique that allows you to tweak classes, modules, or methods at runtime without modifying the original source code.

Sounds powerful? It is.

Sounds risky? Also true.

This post provides a comprehensive guide to monkey patching, covering what it is, why it exists, when to use it, when to avoid it, and how to do it safely in modern Python projects, including Django.

What is Monkey Patching?

Monkey patching means changing or extending code during runtime. You might replace a method, override a function, or add attributes to classes on the fly. This happens without modifying the original source, hence the term “patching.”

The phrase “monkey patch” originated in the Ruby community, but Python’s flexible nature has made it widely adopted here too.

Under the Hood

Python treats everything as an object, and functions/classes are first-class citizens. That means you can reassign methods or attributes as easily as variables.

Example:

class Calculator:
    def add(self, a, b):
        return a + b

# Normal behavior
c = Calculator()
print(c.add(2, 3))  # 5

# Monkey patch the add method
def new_add(self, a, b):
    return f"{a} plus {b} equals {a + b}"

Calculator.add = new_add

print(c.add(2, 3))  # 2 plus 3 equals 5

You’ve just monkey-patched Calculator.add at runtime.

Why Use Monkey Patching?

1. Testing and Mocking

When writing unit tests, you may need to isolate external dependencies like databases, APIs, or time-based operations. Monkey patching lets you inject fake responses without altering the main logic.

Example:

import datetime

def get_today():
    return datetime.date.today()

In testing:

import my_module
my_module.datetime.date.today = lambda: datetime.date(2025, 1, 1)

2. Hotfixing Bugs in Dependencies

Let’s say you found a bug in a third-party library, but there’s no time to fork and patch it properly. You can monkey patch the problematic function locally while waiting for an official fix.

3. Extending Library Behavior

Sometimes, you need a slight tweak to a library function like logging, filtering, or feature toggling, but it doesn’t provide a hook or extension point. Monkey patching fills that gap.

How to Monkey Patch (The Right Way)

You can patch:

  • Methods in classes
  • Functions in modules
  • Properties and constants

Example:

import math

# Override math.sqrt
def custom_sqrt(x):
    print("Calling custom sqrt")
    return x ** 0.5

math.sqrt = custom_sqrt
print(math.sqrt(9))  # Calling custom sqrt → 3.0

Monkey Patching in Testing (Better Approach)

Instead of hardcoding patches, use the built-in unittest.mock.patch()  it’s safer, scoped, and auto-reversible.

from unittest.mock import patch
import my_module

def test_fetch_data():
    with patch("my_module.requests.get") as mock_get:
        mock_get.return_value.json.return_value = {"status": "ok"}
        assert my_module.fetch_data() == {"status": "ok"}

This ensures the patch is active only inside the with block or test function.

Monkey Patching in Django

Django is extensible, but not always easily customizable. Monkey patching lets you hook into internal behaviors without digging into the framework’s guts too much.

Example 1: Patch Django Admin queryset

from django.contrib.admin.options import ModelAdmin

def patched_queryset(self, request):
    qs = super(ModelAdmin, self).get_queryset(request)
    return qs.filter(is_active=True)

ModelAdmin.get_queryset = patched_queryset

Example 2: Patch signal dispatching

from django.db.models.signals import pre_save

def patch_dispatch(self, sender, **kwargs):
    print("Patched signal called!")

pre_save.dispatch = patch_dispatch

Tip: Use these patches only in development or controlled environments, as they may disrupt internal functionality.

Real-World Use Cases

Use CaseDescription
Fixing bugs in dependenciesPatch buggy methods until a fix is released.
Mocking time or I/O operationsReplace calls to datetime.now() or open() for deterministic testing.
Customizing Django adminOverride built-in behaviors for specific admin views.
Changing behavior in CMS pluginsPatch misbehaving Wagtail/Django CMS components.
Dynamic feature togglingEnable/disable features at runtime without deployment.

Risks and Dangers

Monkey patching can become a slippery slope:

1. Hard to Understand

Other developers won’t expect methods to behave differently from their definitions. Surprise overrides lead to confusion and bugs.

 2. Breaks on Updates

Your patch might depend on internal logic or private methods. A version update can silently break your patch.

3. Global Impact

Monkey patching affects all instances globally, not just the one you intended.

Best Practices

TipExplanation
Use sparinglyOnly patch when other solutions aren’t viable.
Limit to tests or devAvoid using monkey patches in production unless absolutely necessary.
Document it clearlyAdd comments explaining what and why you patched.
Use context managersPrefer unittest.mock.patch() to limit patching scope.
Patch at startupIf patching globally, do it in apps.py or main wsgi.py.
Monitor library changesRegularly check if your patches are still necessary.

Summary

Monkey patching is a double-edged sword. It empowers you to:

  • Patch bugs
  • Mock dependencies
  • Customize behavior
  • Build flexible tests
  • But it also introduces:
  • Fragile code
  • Debugging nightmares
  • Upgrade risks

Use it only when necessary, document it well, and always explore alternatives first.

Conclusion

Monkey patching is a powerful tool, best kept in a locked drawer. Use it sparingly, only when conventional approaches fail. When handled with care, it offers remarkable flexibility. But if misused, it can lead to elusive, hard-to-debug problems that will haunt your future self. Treat it with the respect it demands.

Horilla Editorial Team Author

Horilla Editorial Team is a group of experienced writers and editors who are passionate about HR software. We have a deep understanding of the HR landscape and are committed to providing our readers with the most up-to-date and informative content. We have written extensively on a variety of HR software topics, including applicant tracking systems, performance management software, and payroll software etc. We are always looking for new ways to share our knowledge with the HR community. If you have a question about HR software, please don't hesitate to contact us.