Python Decorator用于打印函数执行的每一行

发布于 2021-01-29 15:08:01

我想出于调试目的,打印出与python方法中执行的每一行有关的内容。

例如,如果该行中有一些赋值,我想打印为该变量分配的值,如果有一个函数调用,我想打印出该函数返回的值,等等。

因此,例如,如果我要使用装饰器,则将其应用于函数/方法,例如:

@some_decorator
def testing() : 
    a = 10
    b = 20
    c = a + b
    e = test_function()

调用功能测试时,应打印以下内容:

a = 10
b = 20  
c = 30
e = some_value

有什么办法可以做到这一点?更重要的是,我想知道我是否可以编写可以逐行通过其他代码的代码,检查它是哪种类型的指令,等等。或者也许像我们可以找到一个字典来找出其中的所有变量一个类,我能否得到像数据结构这样的字典来获取函数中的每条指令,这是元程序所能获得的。

因此,我特别在寻找使用装饰器的解决方案,因为我很好奇是否有一个装饰器可以逐行遍历整个功能,并逐行装饰它,但是任何一种解决方案都是受欢迎的。

提前致谢。

关注者
0
被浏览
83
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    这样的事情怎么样?这对您有用吗?

    调试上下文:

    import sys
    
    class debug_context():
        """ Debug context to trace any function calls inside the context """
    
        def __init__(self, name):
            self.name = name
    
        def __enter__(self):
            print('Entering Debug Decorated func')
            # Set the trace function to the trace_calls function
            # So all events are now traced
            sys.settrace(self.trace_calls)
    
        def __exit__(self, *args, **kwargs):
            # Stop tracing all events
            sys.settrace = None
    
        def trace_calls(self, frame, event, arg): 
            # We want to only trace our call to the decorated function
            if event != 'call':
                return
            elif frame.f_code.co_name != self.name:
                return
            # return the trace function to use when you go into that 
            # function call
            return self.trace_lines
    
        def trace_lines(self, frame, event, arg):
            # If you want to print local variables each line
            # keep the check for the event 'line'
            # If you want to print local variables only on return
            # check only for the 'return' event
            if event not in ['line', 'return']:
                return
            co = frame.f_code
            func_name = co.co_name
            line_no = frame.f_lineno
            filename = co.co_filename
            local_vars = frame.f_locals
            print ('  {0} {1} {2} locals: {3}'.format(func_name, 
                                                      event,
                                                      line_no, 
                                                      local_vars))
    

    调试装饰器:

    def debug_decorator(func):
        """ Debug decorator to call the function within the debug context """
        def decorated_func(*args, **kwargs):
            with debug_context(func.__name__):
                return_value = func(*args, **kwargs)
            return return_value
        return decorated_func
    

    用法

    @debug_decorator
    def testing() : 
        a = 10
        b = 20
        c = a + b
    
    testing()
    

    输出量

    ###########################################################
    #output:
    #   Entering Debug Decorated func
    #     testing line 44 locals: {}
    #     testing line 45 locals: {'a': 10}
    #     testing line 46 locals: {'a': 10, 'b': 20}
    #     testing return 46 locals: {'a': 10, 'b': 20, 'c': 30}
    ###########################################################
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看