ChaimG
ChaimG

Reputation: 7514

Python: How to log all class method calls

I am trying to log all method calls for an object. By overriding __getattribute__, I can intercept these calls and print them. My actual object has dozens of methods. To simplify, let's look at a simpler object. Something like this:

class Classy:
    def do_it(self):
        print('We did it!')

    def __getattribute__(self, attr):
        print(f'Calling {attr}')
        return Classy.__getattribute__(self, attr)


c = Classy()
c.do_it()

This code throws:

RecursionError: maximum recursion depth exceeded while calling a Python object

How can __getattribute__ look up a method in the child class while bypassing a call to itself?

EDIT: Interestingly, the call to __init__() bypassed __getattribute__. Instead, the error was triggered by the call to do_it(). That might be a clue.

EDIT2: This is a related question. But after studying the answers there, it still wasn't clear (to me at least) that calls to the parent's __getattribute__ method would in turn get the child class method.

Upvotes: 0

Views: 591

Answers (2)

tituszban
tituszban

Reputation: 5152

You need to access the underlying object instead of your class:

class Classy:
    def do_it(self):
        print('We did it!')

    def __getattribute__(self, attr):
        print(f'Calling {attr}')
        return object.__getattribute__(self, attr)

Upvotes: 1

chepner
chepner

Reputation: 531185

You need to call the parent's __getattribute__ method, which is what would have been called had you not defined Classy.__getattribute__.

class Classy:
    def do_it(self):
        print('We did it!')

    def __getattribute__(self, attr):
        print(f'Calling {attr}')
        return super().__getattribute__(attr)

Upvotes: 2

Related Questions