Nhảy đến nội dung chính

Monkey patch

Monkey patchmột kỹ thuật trong Python (và các ngôn ngữ động khác), dùng để thay đổi hoặc ghimở đèrộng hành vi của một hàm, phươngmethod, thức,class, hoặc classmodule sautại khi nóthời đãiểm runtime (lúc chương trình đang chạy) mà không sửa mã gốc.

được định nghĩa, mà không cầnkhi:

chỉnh
  • Không thể/chưa thể sửa filemã nguồn gốc.

  • Muốn mở rộng thư viện bên thứ 3

  • Override tạm thời một behavior

Nói đơn giản:

Bạn thay thế một hàm hoặc class trong thư viện gốc bằng hàm của bạn – ngay lúc chương trình đang chạy!

Cấu trúc cơ bản

# Module gốc (giả sử không thể sửa)
class Animal:
    def speak(self):
        return "Gâu gâu"

# Monkey patch hàm speak
def meow(self):
    return "Meo meo"

Animal.speak = meow

# Test
a = Animal()
print(a.speak())  # 👉 Meo meo

Ví dụ dễvới hiểmodule tiêu chuẩn Python

Giả sử bạn muốn override math.sqrt để log mỗi lần gọi:

import math

original_sqrt = math.sqrt

def logged_sqrt(x):
    print(f"√{x} was called")
    return original_sqrt(x)

math.sqrt = logged_sqrt

print(math.sqrt(9))  # 👉 log + 3.0

Monkey patch method của class

class User:
    def greet(self):
        return "Hello"

def custom_greet(self):
    return "Xin chào!"

User.greet = custom_greet

u = User()
print(u.greet())  # 👉 Xin chào!

Monkey patch trong unit test

Rất phổ biến khi test cần thay thế tạm hàm nhưgọi vầy:API, DB, hoặc logic tốn thời gian.

#import trongmyapp.utils

payment_entry/payment_entry.pyoriginal = myapp.utils.get_current_time

def hello(fake_time():
    print(return "Hello2025-01-01"

frommyapp.utils.get_current_time VHTerp")= fake_time

BạCách hiện khôngđại muốn(với sửa trực tiếp file, bạn làm như vầy trong app của bạn:unittest.mock)

#from trongunittest.mock app/patches/my_patch.pyimport defpatch

custom_hello(with patch('myapp.utils.get_current_time', return_value="2025-01-01"):
    print(myapp.utils.get_current_time())  # 👉 2025-01-01

Kỹ thuật monkey patch nâng cao

  1. Patch theo điều kiện
if settings.DEBUG:
    module.func = debug_version
else:
    module.func = prod_version

2. Chỉ patch một instance (không toàn bộ class)

import types

class A:
    def say(self): return "HelloHello"

froma My= AppA()
👋a.say = types.MethodType(lambda self: "Xin chào", a)

print(a.say())  # 👉 Xin chào

Monkey patch và thư viện bên thứ 3

Ví dụ override hàm trong thư viện requests:

import requests

_original_get = requests.get

def my_get(*args, **kwargs):
    print(f"GET called: {args[0]}")
    defreturn patch():_original_get(*args, from**kwargs)

payment_entry import payment_entry
    payment_entry.hellorequests.get = custom_hellomy_get