我正在尝试从单例类中捕获函数调用而不覆盖该方法。
目前我正在这样做:
class MyClass
oldMethod = None
def __init__(self):
c = Class.Instance()
self.oldMethod = c.Method #make a copy to the pointer of the original function
c.Method = self.NewMethod #redirect it
def NewMethod(self, x, a):
self.oldMethod(x, a) #call the old function
#My Stuff
我正在尝试捕获'event'(作为方法调用)和此方法调用的参数。有没有其他方法来做“被动地”捕获它,只是听取并获取参数。
注意:我无法访问singleton类的代码。
由于
答案 0 :(得分:1)
您提到您希望在正常操作期间拦截方法调用,而不仅仅是在调试期间。这个解决方案与另一个答案不同,它使用Proxy pattern方法创建一个新对象,它将成为对原始对象的所有调用的一种包装。在代理级别,您可以根据需要记录和监控呼叫。
<强> person.py 强>
为了演示代码,我在Person
模块中创建了一个名为person
的示例类。我们可以假装这是你无法修改代码的模块。
class Person(object):
def __init__(self, name=None):
self.name = name
def greet(self, greeting='hello'):
print '%s %s' % (greeting, self.name)
def __repr__(self):
return "Person(%r)" % self.name
<强> example.py 强>
在下面的代码中,我们创建了一个名为ProxyPerson
的代理对象,当使用它而不是Person
时,它的行为与它相同,并且具有记录对greet方法的所有调用的附加行为。您注意到它使用*args, **kwargs
所以Person将来可能会有不同的签名,但如果进行了更改,代码将不会中断。
import person
class ProxyPerson(person.Person):
def greet(self, *args, **kwargs):
print '--- greet() self=%r args=%r kwargs=%r' % (self, args, kwargs)
super(ProxyPerson, self).greet(*args, **kwargs)
#person.Person = ProxyPerson #uncomment to monkey patch Person
jack, jill = person.Person('Jack'), ProxyPerson('Jill')
for p in jack, jill:
p.greet()
p.greet('hi')
p.greet(greeting='why hello')
常规输出
下面的输出显示了使用原始Person类或使用ProxyPerson时的执行差异。这些示例还包括没有位置参数的调用,带位置参数的调用,最后还包含关键字参数。
hello Jack
hi Jack
why hello Jack
--- greet() self=Person('Jill') args=() kwargs={}
hello Jill
--- greet() self=Person('Jill') args=('hi',) kwargs={}
hi Jill
--- greet() self=Person('Jill') args=() kwargs={'greeting': 'why hello'}
why hello Jill
Monkey修补输出
最后,可以Monkey patch person.Person
类指向ProxyPerson。您可以通过在example.py
中注释掉猴子补丁行来试验这种方法。这种情况下的输出如下:
--- greet() self=Person('Jack') args=() kwargs={}
hello Jack
--- greet() self=Person('Jack') args=('hi',) kwargs={}
hi Jack
--- greet() self=Person('Jack') args=() kwargs={'greeting': 'why hello'}
why hello Jack
--- greet() self=Person('Jill') args=() kwargs={}
hello Jill
--- greet() self=Person('Jill') args=('hi',) kwargs={}
hi Jill
--- greet() self=Person('Jill') args=() kwargs={'greeting': 'why hello'}
why hello Jill
猴子修补的好处是所有未来的person.Person实例实际上都是已创建的代理对象的实例。猴子修补带来了它自己的一系列问题,在使用之前你应该记住这些问题。
答案 1 :(得分:0)
你可以使用winpdb这是一个非常好用的python图形化调试器。所以你只需打开有问题的python脚本,在你想要观看的任何类中以任何方式设置breakpoint。它将在那一点暂停,并向您显示变量的状态以及每次调用该方法时的变量。