我如何构建一个跟踪python调用的能力?

时间:2013-02-08 06:23:02

标签: python python-2.7 trace

假设我有一些python代码,例如某个类在某处定义,无法修改

class MyClass(object):

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

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

这可能吗,这怎么做得最好?

4 个答案:

答案 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的文档非常糟糕,所以我无法弄清楚究竟发生了什么,但我认为这是一个非常酷的问题,祝你好运。