• 坚守一条红线 维护生态安全(在习近平新时代中国特色社会主义思想指引下——新时代新作为新篇章) 2019-11-12
  • 《辉煌中国》第五集《共享小康》 2019-11-12
  • 这事咋办No.2丨申请西安保障性住房必看 花生让你有房住 2019-11-11
  • 预热世界杯 玩法各异!3张竞彩红单了解一下 2019-10-18
  • 崇拜不劳而获是腐败的根源之一,正气不足是腐败的第二个根源,沉迷于初级趣味易滋生腐败,提高素质力争不想腐,以医者之心防治腐败。 2019-10-09
  • 人民日报评论员随笔:让文化热情涵养更多经典 2019-10-09
  • 国产手机跟进“刘海屏”,凸显苹果在智能手机市场的影响力 2019-10-05
  • 世界杯倒计时:球迷街头狂欢为自己的国家打Call 2019-10-02
  • 紫光阁中共中央国家机关工作委员会 2019-09-24
  • 洪崖洞客流激增 渝中开通2条应急通道12辆公交车驰援 2019-09-24
  • 中央环保督察“回头看”10省区问责630人 2019-09-19
  • 天津举办改善营商环境专题讲座 2019-09-19
  • 日本核能行业誓言日本将在今年内重新启用核电 2019-09-03
  • 中国保险行业协会发布汽车后市场配件合车标准 2019-09-02
  • 晋中市通报五起违反中央八项规定精神问题 2019-08-30
  • 当前位置 > CPDA数据分析师 > “数”业专攻 > Python开发中如何使用Hook技巧

    四川快乐12前三直遗漏:Python开发中如何使用Hook技巧

    浙江快乐彩和值走势图 www.pn-vs.com 来源:数据分析师 CPDA | 时间:2017-11-02 | 作者:admin

    什么是Hook,就是在一个已有的方法上加入一些钩子,使得在该方法执行前或执行后另在做一些额外的处理,那么Hook技巧有什么作用以及我们为什么需要使用它呢,事实上如果一个项目在设计架构时考虑的足够充分,模块抽象的足够合理,设计之初为以后的扩展预留了足够的接口,那么我们完全可以不需要Hook技巧。但恰恰架构人员在项目设计之初往往没办法想的足够的深远,使得后续在扩展时深圳面临重构的痛苦,这时Hook技巧似乎可以为我们带来一记缓兵之计,通过对旧的架构进行加钩子来满足新的扩展需求。

     

    Python开发中如何使用Hook技巧

     

    下面我们就来看看如果进行Hook处理,我们按照Hook的对象的层级来逐一介绍

     

    对类进行Hook

    也就是说我们得钩子需要监控到类的创建等操作,然后在此之前或之后做我们希望的操作

     

    1、Hook类的创建

    你可以在写一个类的时候为其添加__metaclass__属性

    class Foo(Bar): __metaclass__ = something…

    Python创建类的过程是这样的:

    Foo中有__metaclass__这个属性吗?如果是,Python会在内存中通过__metaclass__创建一个名字为Foo的类。如果Python没有找到__metaclass__,它会继续在Bar(父类)中寻找__metaclass__属性,并尝试做和前面同样的操作。如果Python在任何父类中都找不到__metaclass__,它就会在模块层次中去寻找__metaclass__,并尝试做同样的操作。如果还是找不到__metaclass__,Python就会用内置的type来创建这个类对象。

    所以我们需要在给__metaclass__属性的值是一个能够创建一个类的东西,即一个继承type的类。

    比如:

    class Singleton(type): def__init__(cls, name, bases, dict): super(Singleton, cls).__init__(name, bases, dict) cls._instance = None def__call__(cls, *args, **kw): if cls._instance is None: cls._instance = super(Singleton, cls).__call__(*args, **kw) return cls._instanceclass MyClass(object): __metaclass__ = Singleton

    Singleton就是一个能够创建类的对象,因为它继承了type

    也正因为此,我们可以在Singleton这个类中去监控MyClass的创建过程

     

    2、Hook实例属性

    这里我们需要操作的属性是__getattribute__和__getattr__

    object.__getattribute__(self, name) :无论访问存在还是不存在的属性都先访问该方法

    object.__getattr__(self, name) :当不存在__getattribute__方法或者引发了AttributeError异常时访问该方法

    class C(object): a = 'abc' def __getattribute__(self, *args, **kwargs): print(__getattribute__() is called) return object.__getattribute__(self, *args, **kwargs) def __getattr__(self, name): print(__getattr__() is called) return namec = C()print c.a__getattribute__() is calledabcprint c.aa__getattribute__() is called__getattr__() is calledaa

    可以看到,访问已有属性a时,__getattribute__被调用,访问未定义的属性aa时__getattribute__先被调用,接着__getattr__被调用

     

    3、Hook类属性

    python描述符是一个“绑定行为”的对象属性,在描述符协议中,它可以通过方法重写属性的访问。这些方法有 __get__(), __set__(), 和__delete__()。如果这些方法中的任何一个被定义在一个对象中,这个对象就是一个描述符。

    class Desc(object): def __get__(self, instance, owner):print(__get__...) def __set__(self, instance, value):print('__set__...')class TestDesc(object): x = Desc()t = TestDesc()t.x__get__...

    - self: Desc的实例对象,其实就是TestDesc的属性x
    - instance: TestDesc的实例对象,其实就是t
    - owner: 即谁拥有这些东西,当然是 TestDesc这个类,它是最高统治者,其他的一些都是包含在它的内部或者由它生出来的

    为了让描述符能够正常工作,它们必须定义在类的层次上。否则Python无法自动为你调用__get__和__set__方法。

    而根据之前对类方法的说明,引用t.x的时候是否会先引用TestDesc的__getattribute__方法呢?答案是会的,其实访问属性时在python中真实的查找顺序是这样的:

    1)__getattribute__(), 无条件调用

    2)数据描述符(定义了__set__或__delete__的描述符):由1)触发调用 (若人为的重载了该 __getattribute__() 方法,可能会导致无法调用描述符)

    3)实例对象的字典

    4)类的字典

    5)非数据描述符(只定义了__get__的描述符)

    6)父类的字典

    7)__getattr__() 方法

     

    4、使用修饰符来Hook类

    def singleton(cls, *args, **kw): instances = {} def _singleton(): if cls not in instances: instances[cls] = cls(*args, **kw) return instances[cls] return [email protected] MyClass(object): a = 1 def __init__(self, x=0): self.x = x

    我们使用singleton方法把MyClass修饰为了一个单例模式,同时我们也在singleton方法中实现了对MyClass实例过程的监控。

     

    对方法进行Hook

    1、修饰符来Hook方法

    1)修饰不带参数的方法

    def something(func): def wrap(): print start func() print end return [email protected] func(): pass

    2)修饰带参数的方法

    def something(func): defwrap(*args,**kargv):print startfunc(*args,**kargv)print end return [email protected] func(a,b): pass

    3)使用带参数的修饰符来修饰方法

    def something(a,b): def new_func(func):def wrap(*args,**kargv): print a func(*args,**kargv) print breturn wrap return [email protected](1,2)def func(a,b): pass

     

    其他Hook

    1、Hook内建方法

    #Hookopen方法real_open = __builtins__.open__builtin__.open = my_open#Hookimport方法real_importer = __import____builtins__.__import__ = my_importer

    上述操作使得my_open代替了python内置的open方法,故而我们可以使用我们自己的my_open方法来监控后续对open方法的调用了

     

    2、Monkey Patch

    from SomeOtherProduct.SomeModule import SomeClassdef speak(self): return "ookookeeeeeeeee!"SomeClass.speak = speak

    实际上这是所有语言都会使用到的Hook技巧,往往在我们使用了第三方的包,希望在之上做一些扩展,但又不想改动原有的代码时使用

     

    多说一句

    上述提到了修饰符的操作,那么我们在使用修饰符时有一些小技巧需要了解

    1、使用functools

    防止使用修饰器后函数签名被改变

    from functools import wrapsdef my_dec(func): @wraps(func) def wrapped():print %siscalled%func.__name__return func() return [email protected]_decdef foo(): pass

    这样处理后,foo方法的签名与被修饰之前保持了一致,否则签名将会变成my_dec方法的签名

     

    2、使用decorator模块来做修饰器

    from decorator import [email protected] wrap(f,*args,**kw): print start f(*args,**kw) print end#这样wrap方法就变成了一个[email protected] func(): print func

     

    3、使用类做修饰器

    class test(object): def__init__(self,func): self._func = func def__call__(self): print start self._func() print [email protected] func(): print funcfunc()startfuncend

    实际应用中很少遇到可以使用一个类作为修饰器,但实际上只要一个类实现了__call__方法,其就可以作为一个修饰器存在了,并且由于类的可操作性较方法更强大,所以类做修饰器也可以实现更丰富的特性。

     

    小编就先聊到这里,今天交流的内容都是硬知识,普通的开发过程中也许并不能使用的上,但了解这些知识对于编程能力的提高很有帮助,也能够帮助你更深入的理解Python的机制。

     

  • 坚守一条红线 维护生态安全(在习近平新时代中国特色社会主义思想指引下——新时代新作为新篇章) 2019-11-12
  • 《辉煌中国》第五集《共享小康》 2019-11-12
  • 这事咋办No.2丨申请西安保障性住房必看 花生让你有房住 2019-11-11
  • 预热世界杯 玩法各异!3张竞彩红单了解一下 2019-10-18
  • 崇拜不劳而获是腐败的根源之一,正气不足是腐败的第二个根源,沉迷于初级趣味易滋生腐败,提高素质力争不想腐,以医者之心防治腐败。 2019-10-09
  • 人民日报评论员随笔:让文化热情涵养更多经典 2019-10-09
  • 国产手机跟进“刘海屏”,凸显苹果在智能手机市场的影响力 2019-10-05
  • 世界杯倒计时:球迷街头狂欢为自己的国家打Call 2019-10-02
  • 紫光阁中共中央国家机关工作委员会 2019-09-24
  • 洪崖洞客流激增 渝中开通2条应急通道12辆公交车驰援 2019-09-24
  • 中央环保督察“回头看”10省区问责630人 2019-09-19
  • 天津举办改善营商环境专题讲座 2019-09-19
  • 日本核能行业誓言日本将在今年内重新启用核电 2019-09-03
  • 中国保险行业协会发布汽车后市场配件合车标准 2019-09-02
  • 晋中市通报五起违反中央八项规定精神问题 2019-08-30
  • 江西快3下载 中彩在线害了多少人 吉林省快3组合走势图 天天电玩城旧版苹果 德国足球为什么这么强 竞彩足球投注分析预测 二八杠作弊器多少钱 德州梭哈棋牌 时时彩组选120玩法介绍 二码中特18期 体育彩票排列三开奖结果 内蒙古时时彩组三群 浙江20选5开奖查询 足球比分直播新浪网 体彩20选5最新开奖结果查询