Skip to content Skip to sidebar Skip to footer

Python Capture Method Call And Parameters

I'm trying to capture a function call from a singleton class without override the method. Currently I'm doing this: class MyClass oldMethod = None def __init__(self):

Solution 1:

You mentioned that you want to intercept the method calls during normal operations and not just during debugging. This solution is a different approach then the other answer, it uses the Proxy pattern approach of making a new object that will be a sort of wrapper to all the calls to the original object. On the proxy level you can log and monitor the calls as needed.

person.py

To demonstrate the code I've created an example class called Person in person module. We can pretend this is the module which you cannot modify the code.

classPerson(object):def__init__(self, name=None):
        self.name = name

    defgreet(self, greeting='hello'):
        print '%s %s' % (greeting, self.name)

    def__repr__(self):
        return"Person(%r)" % self.name

example.py

In the code below we create a proxy object called ProxyPerson which when used instead of Person behaves identically to it and has the added behavior of logging all calls to the greet method. You notice that it uses *args, **kwargs so Person might have a different signature in the future but the code won't break if changes are made.

import person

classProxyPerson(person.Person):
    defgreet(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')

Regular output

The output below shows the difference in execution when the original Person class is is used or when the ProxyPerson is used. The examples also include calls with no positional arguments, with positional arguments, and finally with keyword arguments.

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 patched output

Finally one can Monkey patchperson.Person class to point to ProxyPerson. You can experiment with this approach by commenting out the monkey patch line in example.py. The output in this case would be as follows:

--- 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

The benefits of monkey patching are that all future instances of person.Person will in fact be instances of the proxy object that has been created. Monkey patching comes with it's own set of issues that you should keep in mind before using it.

Solution 2:

You could use winpdb it's a great easy to use graphical debugger for python. So you Just open the python script in question, setup a breakpoint at whatever methods in whatever classes you want to watch. It will pause at that point and showing you the state of variables and what not at each call to that method.

Post a Comment for "Python Capture Method Call And Parameters"