根据您想要关注的内容(只是函数名?返回值?方法?),您可以通过使用sys.settrace
函数来实现不同的事情。每次执行都会调用您传递给它的函数,您可以根据需要自定义回溯。Bellow 我有一个示例,当我必须了解新程序/包的流程时,我会使用该示例。
来源:
import sys, inspect
class Tracer(object):
def __init__(self):
self.tracing_packages = []
self.whitespace = ' '
self.indent_lvl = 0
def trace(self, frame, event, arg):
# Module info
mod = inspect.getmodule(frame)
if mod:
modpath = mod.__name__
else:
modpath = '<no module>'
# Just return if not interested in package
for to_trace in self.tracing_packages:
if not modpath.startswith(to_trace):
return self.trace
# Other info
fn_name = frame.f_code.co_name
src_lines = inspect.getsource(frame).split('\n')
src_line_start = src_lines[0]
src_line_end = src_lines[-1]
lineno = frame.f_lineno
ws = self.whitespace
# Printing
if event == 'call':
self.indent_lvl += 1
print('%scallin: %s %s %s' % (self.indent_lvl*ws, modpath, fn_name, str(arg)))
elif event == 'return':
if isinstance(arg, object):
ret = type(arg)
else:
ret = str(arg)
print('%sreturn: %s' % (self.indent_lvl*ws, ret))
self.indent_lvl -= 1
return self.trace
def watch_package(self, packname):
self.tracing_packages.append(packname)
例子
这里我只想了解一个叫做PyOCD的包的流程:
>>> import sys, inspect, pyOCD
>>> tracer = Tracer()
>>> tracer.watch_package('pyOCD')
>>> sys.settrace(tracer.trace)
>>> pyOCD.board.MbedBoard.listConnectedBoards()
callin: pyOCD.board.mbed_board listConnectedBoards None
callin: pyOCD.board.mbed_board getAllConnectedBoards None
callin: pyOCD.interface.pyusb_backend getAllConnectedInterface
callin: pyOCD.interface.pyusb_backend __init__ None
callin: pyOCD.interface.interface __init__ None
return: <type 'NoneType'>
return: <type 'NoneType'>
callin: pyOCD.interface.pyusb_backend start_rx None
return: <type 'NoneType'>
return: <type 'list'>
...