3

假设我有一些 python 代码,例如在某处定义的某个类,它不能被修改

class MyClass(object):

    def __init__(self, arg1, arg2):
        do_something...
    def foo(self):
        do_something

现在我想添加一个跟踪功能,例如来自外部的一些机制来跟踪上述类的每个方法调用。我希望能够在例如__init__被调用时打印出来,foo甚至是__del__MyClass.

这可能吗,如何做到最好?

4

4 回答 4

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'}
于 2013-02-08T07:50:56.083 回答
2

创建一个包装原始类的代理类,然后在打印跟踪后委托工作:

 class MyClassProxy(object):

      def __init__(*args, **kwds):
           print 'Initializing'
           self.o = MyClass(*args, **kwds)

      def foo(self):
           print 'Fooing'
           return self.o.foo()
于 2013-02-08T06:27:03.850 回答
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()
于 2013-02-08T06:37:43.457 回答
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 的文档很糟糕,所以我很难弄清楚到底发生了什么,但我认为这是一个很酷的问题,祝你好运。

于 2013-02-08T08:13:04.527 回答