Python 高级特性 猴子补丁(Monkey Patching)
有勇气的牛排
26
Python
2025-07-27 22:51:51
1 前言
1.1 定义
Monkey Paching 是指在程序运行时,动态地修改模块、类或对象的 属性、方法或函数实现。
简单理解:
在不修改源码的情况下,通过运行时“插手”改变代码行为。
1.2 猴子补丁的特征
特征 |
说明 |
动态修改 |
在运行时进行修改,而非编译期或静态定义 |
无需修改原始代码 |
可直接替换第三方库中的方法或属性 |
灵活强大 |
可以快速修改bug、添加日志、做测试 mock |
有风险 |
会影响全局行为,难以调试、维护,肯呢个引入隐藏bug |
2 基本案例
2.1 替换类的方法
class MyClass:
def greet(self):
print("你好")
def new_greet(self):
print("你好呀")
MyClass.greet = new_greet
obj = MyClass()
obj.greet()
2.2 替换内建模块方法
import time
def fake_sleep(seconds):
print(f"正在等待 {seconds} 秒...")
time.sleep = fake_sleep
time.sleep(3)

3 Mokey Patching 的风险
- 维护成本高:被人无法一眼看出代码被修改过。
- 调试困难:难以追踪方法为何行为异常。
- 依赖内部实现:一旦第三方开库升级,补丁可能失效或报错。
- 污染全局状态:所有使用该方法的地方都会影响。
4 典型场景用途
场景 |
示例 |
测试中 mock 系统函数 |
替换time.sleep 、os.path.exist 避免实际等待或依赖 |
修复第三方库bug |
替换其内部方法逻辑(热修复) |
添加日志或监控 |
在不修改源码的前提下加埋点或日志 |
框架底层 hook 插件机制 |
替换默认行为,如 flask 中间件修改 request 随想 |
5 面试回答
Monkey Pathing 是一种在运行时动态修改类或模块的方法或属性的技术,它允许我们不修改原始源码,就能更改第三方库或对象的行为。虽然灵活,但容易带来维护困难和隐藏bug,通常只建议用于测试、调试或临时修复场景。
<h2><a id="1__0"></a>1 前言</h2>
<h3><a id="11__2"></a>1.1 定义</h3>
<p><strong>Monkey Paching</strong> 是指在程序运行时,动态地修改模块、类或对象的 <strong>属性</strong>、<strong>方法</strong>或<strong>函数实现</strong>。</p>
<p>简单理解:</p>
<p>在不修改源码的情况下,通过运行时“插手”改变代码行为。</p>
<h3><a id="12__10"></a>1.2 猴子补丁的特征</h3>
<table>
<thead>
<tr>
<th>特征</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>动态修改</td>
<td>在运行时进行修改,而非编译期或静态定义</td>
</tr>
<tr>
<td>无需修改原始代码</td>
<td>可直接替换第三方库中的方法或属性</td>
</tr>
<tr>
<td>灵活强大</td>
<td>可以快速修改bug、添加日志、做测试 mock</td>
</tr>
<tr>
<td>有风险</td>
<td>会影响全局行为,难以调试、维护,肯呢个引入隐藏bug</td>
</tr>
</tbody>
</table>
<h2><a id="2__19"></a>2 基本案例</h2>
<h3><a id="21__21"></a>2.1 替换类的方法</h3>
<pre><div class="hljs"><code class="lang-python"><span class="hljs-comment"># -*- coding: utf-8 -*-</span>
<span class="hljs-keyword">class</span> <span class="hljs-title class_">MyClass</span>:
<span class="hljs-keyword">def</span> <span class="hljs-title function_">greet</span>(<span class="hljs-params">self</span>):
<span class="hljs-built_in">print</span>(<span class="hljs-string">"你好"</span>)
<span class="hljs-keyword">def</span> <span class="hljs-title function_">new_greet</span>(<span class="hljs-params">self</span>):
<span class="hljs-built_in">print</span>(<span class="hljs-string">"你好呀"</span>)
<span class="hljs-comment"># 打补丁</span>
MyClass.greet = new_greet
obj = MyClass()
obj.greet() <span class="hljs-comment"># 输出: 你好呀</span>
</code></div></pre>
<h3><a id="22__40"></a>2.2 替换内建模块方法</h3>
<pre><div class="hljs"><code class="lang-python"><span class="hljs-comment"># -*- coding: utf-8 -*-</span>
<span class="hljs-keyword">import</span> time
<span class="hljs-keyword">def</span> <span class="hljs-title function_">fake_sleep</span>(<span class="hljs-params">seconds</span>):
<span class="hljs-built_in">print</span>(<span class="hljs-string">f"正在等待 <span class="hljs-subst">{seconds}</span> 秒..."</span>)
<span class="hljs-comment"># 给time.sleep 打补丁</span>
time.sleep = fake_sleep
time.sleep(<span class="hljs-number">3</span>)
</code></div></pre>
<p><img src="https://static.couragesteak.com/article/b26368c4168421bd9773d9d490e27bf3.png" alt="image.png" /></p>
<h2><a id="3_Mokey_Patching__57"></a>3 Mokey Patching 的风险</h2>
<ul>
<li>维护成本高:被人无法一眼看出代码被修改过。</li>
<li>调试困难:难以追踪方法为何行为异常。</li>
<li>依赖内部实现:一旦第三方开库升级,补丁可能失效或报错。</li>
<li>污染全局状态:所有使用该方法的地方都会影响。</li>
</ul>
<h2><a id="4__64"></a>4 典型场景用途</h2>
<table>
<thead>
<tr>
<th>场景</th>
<th>示例</th>
</tr>
</thead>
<tbody>
<tr>
<td>测试中 mock 系统函数</td>
<td>替换<code>time.sleep</code>、<code>os.path.exist</code> 避免实际等待或依赖</td>
</tr>
<tr>
<td>修复第三方库bug</td>
<td>替换其内部方法逻辑(热修复)</td>
</tr>
<tr>
<td>添加日志或监控</td>
<td>在不修改源码的前提下加埋点或日志</td>
</tr>
<tr>
<td>框架底层 hook 插件机制</td>
<td>替换默认行为,如 flask 中间件修改 <code>request</code> 随想</td>
</tr>
</tbody>
</table>
<h2><a id="5__73"></a>5 面试回答</h2>
<p>Monkey Pathing 是一种在运行时动态修改类或模块的方法或属性的技术,它允许我们不修改原始源码,就能更改第三方库或对象的行为。虽然灵活,但容易带来维护困难和隐藏bug,通常只建议用于测试、调试或临时修复场景。</p>
评论区