Better way to log method calls in Python?
我们可以将某种日志装饰器编码为echo函数/方法调用,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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): ... |
但是,如果我们想记录方法调用而不在每个方法定义前面放置那么多@log呢?有什么方法可以将一个decorator放在类定义之上,使其所有方法调用都被修饰/记录?还是有其他更好有趣的方法来代替装饰?
这可能是杀伤力过大,但有一个跟踪功能工具可以通知您程序中的大量活动:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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) |
我不确定您的用例是什么,但是一般来说,我会更多地考虑您正试图解决的问题到底是什么。
也就是说,这里有一个例子,可以做你想做的,但没有装饰:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #!/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) |
输出:
1 2 3 | called foo called bar called foobar |
请参见将decorator附加到类中的所有函数
然而,正如对这个问题公认的答案所指出的,这通常不是一个好主意。
如果您决定采用面向方面的编程路线,我建议从这里开始:有针对Python的AOP支持库吗?
如果您不想显式地修饰所有的函数,那么您可以获取给定模块的所有函数/方法,并自动应用修饰器。不是最简单的事情,但在python中不可行:)
您还可以尝试使用面向方面的编程框架。
MY2C