18.4.10 栈与帧
除了用于检查代码对象的函数,inspect还包括一些函数可以检查程序执行时的运行时环境。其中大多数函数都处理调用栈,并且操作对象为"调用帧"。帧对象包含当前执行上下文,包括正则运行的代码的引用,正在执行的操作,以及局部和全局变量的值。一般地,这些信息会在产生异常时用来建立traceback;当然,其对于记录日志或调试程序也很有用,因为可以通过查看栈帧来发现传入函数的参数值。
import inspect
import pprint
def recurse(limit,keyword='default',*,kwonly='must be named'):
local_variable = '.' * limit
keyword = 'changed value of argument'
frame = inspect.currentframe()
print('line {} of {}'.format(frame.f_lineno,
frame.f_code.co_filename))
print('locals:')
pprint.pprint(frame.f_locals)
print()
if limit <= 0:
return
recurse(limit - 1)
return local_variable
if __name__ == '__main__':
recurse(2)
recurse()的参数值被包含在帧的局部变量字典中。
使用stack(),还可以访问当前帧到第一个调用者的所有栈帧。这个例子与前面的例子类似,只不过它会一直等待,直到递归结束,再打印栈信息。
import inspect
import pprint
def show_stack():
for level in inspect.stack():
print('{}[{}]\n -> {}'.format(
level.frame.f_code.co_filename,
level.lineno,
level.code_context[level.index].strip(),
))
pprint.pprint(level.frame.f_locals)
print()
def recurse(limit):
local_variable = '.' * limit
if limit <= 0:
show_stack()
return
recurse(limit - 1)
return local_variable
if __name__ == '__main__':
recurse(2)
输出最后一部分表示主程序,这在recurse()函数之外。
还有一些函数可以构建不同上下文中的帧列表,如在处理一个异常时。相关的更多细节可参见trace()、getouterframes()和getinnerframes()的文档。