猴子补丁是在运行时动态修改类、函数或模块行为的技术,它能快速修复第三方库问题但存在安全隐患;因import缓存、__dict__覆盖、装饰器失效及多线程竞争等风险,需在入口处提前打补丁、保留签名、覆盖所有调用路径并严格测试。

什么是猴子补丁,它真的安全吗?
猴子补丁不是“给代码打补丁”,而是运行时动态修改类、函数或模块对象的行为。它能绕过源码限制快速修复或调试第三方库,但__dict__覆盖、装饰器失效、多线程竞争都可能引发静默故障。Python 的 import 缓存机制会让同一模块在不同地方看到不一致的状态——这是最常被忽略的隐患。
如何正确替换一个第三方函数(比如 requests.get)?
直接赋值 requests.get = my_get 看似简单,但若其他模块已导入并缓存了原函数引用,补丁就无效。必须确保补丁发生在所有依赖模块 import 之前,或用更稳妥的方式劫持调用链。
- 优先使用
unittest.mock.patch在测试中临时替换,避免污染全局状态 - 若需全局生效,应在项目入口(如
main.py最顶部)执行补丁,并确认requests尚未被任何模块导入过 - 替换时保留原函数签名:用
@functools.wraps(original_func)包装新函数,否则inspect.signature()会出错 - 别只改
requests.get,还要考虑requests.Session().get和requests.request(),它们底层可能不走同一个入口
为什么对类方法打补丁后实例方法没生效?
常见错误是直接改写了类的 __dict__,但 Python 实例方法查找顺序是:实例 __dict__ → 类 __dict__ → 父类。如果原方法是通过 @property 或描述符实现的,直接赋值到类上会被忽略。
- 检查目标是否为描述符:
hasattr(cls.attr, '__get__'),若是,得用setattr(cls, 'attr', new_descriptor) - 对实例方法补丁,应操作类对象本身,而不是某个实例:
MyClass.method = new_method,而非obj.method = new_method - 若类用了
__slots__,且未声明目标属性名,setattr(MyClass, ...)会静默失败 - 异步框架(如
aiohttp)中,补丁还必须适配协程函数,不能用普通函数替换async def
生产环境该不该用猴子补丁?
可以,但只用于三类场景:紧急线上热修复(且已有回滚方案)、集成测试隔离外部依赖、开发期调试不可控的第三方行为。一旦补丁稳定,应推动上游合并或改用官方扩展点(如 requests.Session.mount() 替代直接 patch get)。补丁逻辑必须写单元测试,且每次升级第三方库后重新验证——因为小版本更新可能重构内部调用链,让补丁失效或引发新问题。
立即学习“Python免费学习笔记(深入)”;


















