首页 > 编程语言 >python的猴子补丁monkey patch

python的猴子补丁monkey patch

时间:2023-01-30 11:34:49浏览次数:53  
标签:monkey python module patch xx import sub

monkey_patch,这个词多少年前就在python编程中了解过,但是一直没有系统的总结下,近日又再次遇到这个概念,故此记录一下。

 

在python中由于其内部的实现机制导致其具备较大的编程灵活性,也正是如此,monkey_patch在python中更加有应用场景。monkey_patch这个概念就是在python程序运行过程中对其原有的某些函数、类或模块进行替换,monkey_patch往往出现在程序启动最初的地方。比较形象的一个例子

可以说在原有项目不进行细节改动的情况下我们通过使用monkey_patch可以实现对原有项目中的功能函数替换的目的,这也是为啥叫patch的原因。

 

 

 

给出一个自己的toy code:

 

python的猴子补丁monkey patch_命名空间

 

 

 

python的猴子补丁monkey patch_python_02

 

 

 

 

main.py

"""
import sub

import monkey_patch
monkey_patch.mk()

sub.sub_fun()
"""


import monkey_patch
monkey_patch.mk()

from sub import sub_fun


sub_fun()

 

 sub.py

def sub_fun():
print("this is sub module")

 

monkey_patch.py

import sub
from sub import sub_fun


def sub_fun2():
print("this is monkey_patch module")


def mk():
sub.sub_fun = sub_fun2
sub.sub_fun.__name__ = "monkey_patch_sub_fun"


sub_fun = sub_fun2
sub_fun.__name__ = "monkey_patch_sub_fun"

 

 

需要注意的是这个monkey_patch对于import xx_module的情况还是比较好处理的,比较不好处理的就是那种from xx_module import xx 

对于这种from xx_module import xx 的情况,我们就需要在monkey_patch中同样编写from xx_module import xx 并且在主文件启动时把这个monkey_patch放在最前面,否则就会失效。

from xx_module import xx 操作其实等价于import xx_module;xx=xx_module.xx,可以说之所以这样的情况monkey_patch不好处理是因为monkey_patch中的函数执行是不能修改其他模块中的变量命名空间的,比如main.py中的变量的命名空间为__main__,monkey_patch.py中变量的命名空间为monkey_patch,如果在main.py中执行from xx_module import xx 操作,那么xx的考虑命名空间的全名为__main__.xx,而import xx_module 这种情况则不论在任何子模块中调用该import都会有相同的命名空间变量xx_module.xx ,因此这种情况才可以在monkey_patch中容易的进行替换。

 

之所以把monkey_patch.mk() 操作放在main.py最初始的地方可以使from xx_module import xx 有效是因为monkey_patch.py中已经执行了from xx_module import xx 这个操作并对此进行了替换,这样其他模块中再次执行from xx_module import xx 就不会有具体的操作,因为已经xx_module下的xx变量已经存在在全局的命名空间下。

 

总的来说, import xx_module 不论在启动模块还是子模块中执行操作后便在命名空间中留下了记录,以后不论任何模块通过xx_module.xx的方式来进行赋值或修改都是直接对全局唯一的变量进行操作的,并且所有模块都可以共享这个全局命名空间下的这个xx_module.xx变量。但是对于from xx_module import xx 操作来说,只有在第一次执行的模块内是可以对这个xx变量进行赋值或修改后其他模块也可以通过from xx_module import xx 方式读取该值的,但是其他模块即使通过该方式读取该值也不能对其修改后使其在所有子模块内被共享,因为此时的xx的命名框架是当前执行模块内的,换句话说如果使用from xx_module import xx 方式的话,只有在其第一次执行的模块内对其进行的操作是可以传递到其他模块的,而其他模块(不是第一次执行from xx_module import xx 操作的模块)对其的修改只在自身模块的命名框架下是有效的。

 

 

from xx_module import xx 方式调用xx,那么在任何子模块中执行后其命名空间都为其所执行模块的名称,也就是说如果是xyz.py模块调用那么其变量名可以视作xyz.xx,这也就是为什么只有第一次执行from xx_module import xx 方式调用的模块才可以对其进行修改。

 

import xx_module方式调用xx_module.xx,那么在所有模块中带命名空间的变量全名为xx_module.xx 。

 

对于整个模块进行monkey_patch替换则需要修改sys.modules中的内容

 

>>> import sys
>>> sys.modules['sys']
<module 'sys' (built-in)>
>>>
>>> sys.modules['os']=sys.modules['sub']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'sub'
>>> import sub
>>> sys.modules['os']=sys.modules['sub']
>>>
>>> os
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>> import os
>>> os.sub_fun


 

参考:


​https://blog.51cto.com/iceyao/1695266​

​https://zhuanlan.zhihu.com/p/37679547​

 

标签:monkey,python,module,patch,xx,import,sub
From: https://blog.51cto.com/u_15642578/6026153

相关文章

  • python代码实现将PDF文件转为文本及其对应的音频
    代码地址:​​https://github.com/TiffinTech/python-pdf-audo​​  ============================================  importpyttsx3,PyPDF2#insertnameofyourpdfpd......
  • python进程绑定CPU的意义
    1.绑定CPU后对计算密集型的任务可能会一定程度上提升运算性能:(小幅度的性能提升,甚至小幅度落后,总之就是差别不大)对比1代码A:importosfrommultiprocessingimportProcessfr......
  • python进程绑定CPU的一些Demo
    从​​中知道如何对python进程设置CPU绑定,本文对此进行一些延伸,给出一些例子:代码1:importosfrommultiprocessingimportProcessimporttimecpu_avia=os.sched_getaffini......
  • python文字转语音
    依赖pyttsx3库pipinstallpyttsx3 yuyin_test1.pyimportpyttsx3engine=pyttsx3.init()engine.say("Fourthlettersoftransitinthespringbreezeasyo......
  • python3-pip
    一、pip介绍Python官网中的安装包中已经自带了pip,在安装时默认选择安装。安装完python后需要手动配置pip的环境变量,cmd命令可以查看pip是否可用:pip或者pip-h二、命令......
  • Python Numpy 中的打印设置函数set_printoptions
    一概述np.set_printoptions()用于控制Python中小数的显示精度。二解析np.set_printoptions(precision=None,threshold=None,linewidth=None,suppress=None,......
  • python2--安装es报错:error in elastic-transport setup command: 'install_requires'
    今天使用python2安装es模块时报错:  原因是pip(模块管理工具)版本过低,需先升级pip,再进行安装先替换pip的镜像,默认镜像拉取慢,还可能会失败cd~;mkdir.pip;touch.p......
  • python爬虫(二)- HTML解析之XPath
    HTML解析通过urllib、requests,都可以拿到HTML内容。HTML的内容返回给浏览器,浏览器就会解析它,并对它渲染。HTML超文本表示语言,设计的初衷就是为了超越普通文本,让文本表......
  • Python用KShape对时间序列进行聚类和肘方法确定最优聚类数k可视化|附代码数据
    全文链接:http://tecdat.cn/?p=27078最近我们被客户要求撰写关于KShape的研究报告,包括一些图形和统计输出。时序数据的聚类方法,该算法按照以下流程执行。使用基于互相关......
  • curl_cffi: 支持原生模拟浏览器 TLS/JA3 指纹的 Python 库
    原文首发于我的博客:https://yifei.me/note/2719越来越多的网站开始使用TLS指纹反爬虫,而Python中竟然没有任何方法解决这个问题。前一阵看到由国外大神写了一个curl-......