Python 用于打印函数执行的每一行的装饰器
Python Decorator for printing every line executed by a function
出于调试目的,我想打印出与 python 方法中执行的每一行有关的内容。
例如,如果行中有一些赋值,我想打印为该变量赋值的值,如果有函数调用,我想打印出函数返回的值,等等。
因此,例如,如果我要使用装饰器,则应用于 function/method 例如:
@some_decorator
def testing() :
a = 10
b = 20
c = a + b
e = test_function()
调用函数测试时,应打印以下内容:
a = 10
b = 20
c = 30
e = some_value
有什么方法可以实现吗?更根本的是,我想知道我是否可以编写一个代码来逐行检查其他代码,检查它是什么类型的指令,等等。或者我们可以得到一个字典来找出所有变量a class,我可以得到一个像数据结构这样的字典来获取函数中的每条指令,这是元程序可以获得的一样好。
因此,我特别在寻找一种使用装饰器的解决方案,因为我很好奇是否可以拥有一个可以逐行遍历整个函数并逐行装饰它的装饰器,
但欢迎任何和所有解决方案。
提前致谢。
这样的事情怎么样?这对你有用吗?
调试上下文:
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}
###########################################################
出于调试目的,我想打印出与 python 方法中执行的每一行有关的内容。
例如,如果行中有一些赋值,我想打印为该变量赋值的值,如果有函数调用,我想打印出函数返回的值,等等。
因此,例如,如果我要使用装饰器,则应用于 function/method 例如:
@some_decorator
def testing() :
a = 10
b = 20
c = a + b
e = test_function()
调用函数测试时,应打印以下内容:
a = 10
b = 20
c = 30
e = some_value
有什么方法可以实现吗?更根本的是,我想知道我是否可以编写一个代码来逐行检查其他代码,检查它是什么类型的指令,等等。或者我们可以得到一个字典来找出所有变量a class,我可以得到一个像数据结构这样的字典来获取函数中的每条指令,这是元程序可以获得的一样好。
因此,我特别在寻找一种使用装饰器的解决方案,因为我很好奇是否可以拥有一个可以逐行遍历整个函数并逐行装饰它的装饰器, 但欢迎任何和所有解决方案。
提前致谢。
这样的事情怎么样?这对你有用吗?
调试上下文:
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}
###########################################################