Better way to log method calls in Python?

2019-02-06 06:22发布

We can code out some sort of logging decorator to echo function/method calls like the following:

def log(fn):
    ...

@log
def foo():
    ...

class Foo(object):
    @log
    def foo(self):
        ...

    @log
    def bar(self, a, b):
        ...

    @log
    def foobar(self, x, y, z):
        ...

But what if we are like to log method calls without putting that many @log in front of each meth definition? Is there some way to just put one decorator above a class definition to make all its method calls decorated/logged? Or are there some other better and interesting ways to do that instead of decorator?

4条回答
Juvenile、少年°
2楼-- · 2019-02-06 06:56

I'm not sure what your use case is for this, but generally, I would think more about what exactly is the problem that you're trying to solve.

That said, here's an example that might do what you want but without a decorator:

#!/usr/bin/env python
import inspect


class Foo(object):

    def foo(self):
        pass

    def bar(self, a, b):
        pass

    def foobar(self, x, y, z):
        pass

    def __getattribute__(self, name):
        returned = object.__getattribute__(self, name)
        if inspect.isfunction(returned) or inspect.ismethod(returned):
            print 'called ', returned.__name__
        return returned


if __name__ == '__main__':
    a = Foo()
    a.foo()
    a.bar(1, 2)
    a.foobar(1, 2, 3)

Output:

called  foo
called  bar
called  foobar
查看更多
聊天终结者
3楼-- · 2019-02-06 06:57

See Attaching a decorator to all functions within a class

However, as the accepted answer to that question points out, it generally isn't a good idea.

If you decide to go the aspect oriented programming route, I suggest starting here: Any AOP support library for Python?

查看更多
女痞
4楼-- · 2019-02-06 06:59

Well, If you do not want to explicitly decorate all your functions, you can get all the functions/methods of a given module and apply your decorator automatically. not the easiest thing but not infeasible in python :)

You can also try an aspect oriented programming framework.

my2c

查看更多
混吃等死
5楼-- · 2019-02-06 07:00

This might be overkill, but there is a trace function facility that will inform you of a great deal of activity within your program:

import sys

def trace(frame, event, arg):
    if event == "call":
        filename = frame.f_code.co_filename
        if filename == "path/to/myfile.py":
            lineno = frame.f_lineno
            # Here I'm printing the file and line number, 
            # but you can examine the frame, locals, etc too.
            print "%s @ %s" % (filename, lineno)
    return trace

sys.settrace(trace)
call_my_function()
sys.settrace(None)
查看更多
登录 后发表回答