假设我有一些python代码,例如某个类在某处定义,无法修改
class MyClass(object):
def __init__(self, arg1, arg2):
do_something...
def foo(self):
do_something
现在我想添加跟踪功能,例如来自外部的一些机制跟踪上述类的每个方法调用。我希望能够在例如__init__
被调用,foo
甚至是__del__
MyClass
方法时打印出来。
这可能吗,这怎么做得最好?
答案 0 :(得分:2)
创建一个包装原始类的代理类,然后在打印跟踪后委派工作:
class MyClassProxy(object):
def __init__(*args, **kwds):
print 'Initializing'
self.o = MyClass(*args, **kwds)
def foo(self):
print 'Fooing'
return self.o.foo()
答案 1 :(得分:2)
您可以创建跟踪装饰器并将其附加到类实例或类定义的所有方法,如decorate_methods
函数中所示。
import functools
import inspect
import types
class TestClass(object):
def func1(self):
pass
def func2(self, a, b):
pass
def trace(func):
@functools.wraps(func)
def decorator(*args, **kwargs):
print "TRACE:", func.__name__, args, kwargs
return func(*args, **kwargs)
return decorator
def decorate_methods(obj, decorator):
for name, func in inspect.getmembers(obj):
if isinstance(func, types.MethodType):
setattr(obj, name, decorator(func))
# Apply the decorator to a class instance
test1 = TestClass()
decorate_methods(test1, trace)
test1.func1()
test1.func2('bar1', b='bar2')
# Apply the decorator to the class definition
decorate_methods(TestClass, trace)
test2 = TestClass()
test2.func1()
test2.func2('bar1', b='bar2')
脚本的输出将是:
TRACE: func1 () {}
TRACE: func2 ('bar1',) {'b': 'bar2'}
TRACE: func1 (<__main__.TestClass object at 0x7f5a8d888150>,) {}
TRACE: func2 (<__main__.TestClass object at 0x7f5a8d888150>, 'bar1') {'b': 'bar2'}
答案 2 :(得分:1)
使用装饰器,如下所示:
def call_trace(orig_func):
def decorated_func(*args, **kwargs):
print "========>In function: " + orig_func.__name__ + "<========"
orig_func(*args, **kwargs)
return decorated_func
应用此装饰器来跟踪该功能。它在输入函数之前打印函数名称。
例如:
@call_trace
def foo(self):
do_something
希望它有所帮助。
[更新]:您可以使用元类,只需要更改的是将“元类”参数添加到您的类中,如下所示。如您所见,下面的代码将“call_trace”装饰器应用于“ExBase”类中的每个函数。
我昨天试了这个,工作得很好。我也是python的新手。:)def call_trace(orig_func):
def inner_func(*args, **kwargs):
print ("function name:" + str(orig_func.__name__))
orig_func(*args, **kwargs)
return inner_func
class ExMeta(type):
def __new__(cls, name, bases, attrs):
for attr in attrs:
if hasattr(attrs[attr], '__call__'):
attrs[attr] = call_trace(attrs[attr])
return type.__new__(cls, name, bases, attrs)
class ExBase(metaclass=ExMeta):
x = "x"
y = "y"
def __init__(self):
self.__name = "name"
def getname(self):
return self.__name
b = ExBase()
b.getname()
答案 3 :(得分:0)
从github.com/pgbovine/OnlinePythonTutor/tree/master/v3获取OnlinePythonTutor的代码。
你不需要打扰所有的JS东西。将文件解压缩到某个目录中。您可以使用python / path / to / my / OnlinePythonTutor-master / v3 / generate_json_trace my_script.py
运行脚本这将基本上为您提供程序正在逐步完成的所有操作。如果你想查看bdb http://docs.python.org/2/library/bdb.html中的源代码和底层源代码,可能会有点过分。 bdb的文档非常糟糕,所以我无法弄清楚究竟发生了什么,但我认为这是一个非常酷的问题,祝你好运。