Python 模块简介 -- inspect
inspect
模块提供了一些有用的函数来帮助获取对象的信息,例如模块、类、方法、函数、堆栈(trace)、栈帧(frame)、代码对象等。该模块可以检查类的内容、检索方法的源代码、提取函数的参数列表,或者获取并显示详细的堆栈信息。
该模块提供了四种主要功能:
- 类型检查
- 获取源码
- 检查类和函数
- 检查解释器堆栈信息
成员与类型
getcomments
: 获取对象的成员,类似 dir 函数ismodule
: 检查对象是否为模块isclass
: 检查对象是否为类ismethod
: 检查对象是否为方法(绑定方法)isfunction
: 检查对象是否为函数(函数,包括 lambda 函数,非对象方法)isgeneratorfunction
: 检查对象是否为生成器函数isgenerator
: 检查对象是否为生成器istraceback
: 检查对象是否为 tracebackisframe
: 检查对象是否为 frameiscode
: 检查对象是否为 codeisbuiltin
: 检查对象是否为内建函数或方法isroutine
: 检查对象是否为用户自定义或者内建的函数或方法isabstract
: 检查对象是否为抽象基类ismethoddescriptor
: 检查对象是否为方法描述符isdatadescriptor
: 检查对象是否为数据描述符isgetsetdescriptor
: 检查对象是否为非数据描述符ismemberdescriptor
: 检查对象是否为成员描述符
获取源码
getdoc
: 获取对象文档字符串,类似访问对象的__doc__
方法getcomments
: 获取对象最开始的注释行getfile
: 获取对象被定义的模块文件(文本或者编译的二进制)的文件名getmodule
: 获取对象所属的模块名getsourcefile
: 获取对象被的模块的源代码文件名,对象不能为内建的模块、类、函数getsourcelines
: 获取对象定义的源代码内容,返回内容和对象定义所在的行号元组getsource
: 获取对象定义的源代码内容,返回字符串cleandoc
:清除 docstring 中的缩进
类与函数
getclasstree
: 获取给定类列表的继承树getargspec
: 获取函数的参数列表及参数缺省值(在 Python3 中被废弃)getfullargspec
: 获取函数的参数列表、参数缺省值、参数注解等getargvalues
: 获取传递给当前调用栈帧的参数信息formatargspec
: 格式化 getfullargspec() 的返回值formatargvalues
: 格式化 getargvalues() 的返回值getmro
: 获取类的所有基类,返回一个元素,按 mro 的解析顺序返回inspect.getcallargs
: 将传入参数绑定到函数的参数名上,返回一个将参数名字和值作为键值对的字典(按照形参和实际传入参数的位置形成键值对)
解析堆栈
类似于 C 语言,Python 解释器也使用栈帧(Stack frame)机制来管理函数调用。栈帧指的是在堆栈中为当前正在运行的函数分配的区域(或空间)。传第给函数的参数、返回地址(当这个函数结束后必须跳转到该返回地址,即调用者函数的断点处)以及函数所用的内部存储单元(即函数存储在堆栈上的局部变量)都在栈帧中。
getframeinfo(frame, context=1)
: 获取栈帧信息getouterframes(frame, context=1)
: 从 frame 到栈底的所有栈帧,对于 frame 来说,从它到栈底的帧都被称为外部帧getinnerframes(traceback, context=1)
: 获取一个 traceback 对象中的栈帧。currentframe()
: 获取当前正在运行的代码行所在的栈帧,也即当前栈帧stack(context=1)
: 获取获取当前的所有栈帧信息trace(context=1)
: 获取异常时的栈帧信息
frame 对象
frame
对象表示执行帧,即程序运行时函数调用栈中的某一帧。
如果需要获得某个函数相关的栈帧,则必须在调用这个函数且这个函数尚未返回时获取(函数返回时栈帧会被释放)。当前栈帧可以使用 sys 模块的 _getframe
函数、或 inspect 模块的 currentframe
函数获取。
frame
对象包含了一些属性,这些属性对应着在栈帧里存储的数据。
只读属性:
f_back
: 前一个堆栈帧,如果这是底部堆栈帧则为 Nonef_code
: 在这个框架中执行的Code对象f_locals
: 用于查找局部变量的字典f_globals
: 用于全局变量f_builtins
: 用于内置名称
可写属性:
f_trace
f_exc_type
f_exc_value
f_exc_traceback
f_lineno
: 当前代码在文件中行号
使用示例
对传入和函数的参数进行检查:
import functools
import inspect
def check_value(value, name):
if isinstance(value, str) and (not value or value.isspace()):
raise Exception("invalid '{}' value: '{!r}'".format(name, value))
def check_arguments(args):
for name, value in args.items():
check_value(value, name)
def checked_arguments(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
callargs = inspect.getcallargs(func, *args, **kwargs)
print("------>", callargs)
check_arguments(callargs)
return func(*args, **kwargs)
return wrapper
@checked_arguments
def test(a, b, c=1):
print(a, b, c)
test(1, 2)
test(1, 2, 3)
# output:
"""
------> {'a': 1, 'b': 2, 'c': 1}
1 2 1
------> {'a': 1, 'b': 2, 'c': 3}
1 2 3
"""
查看堆栈信息:
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("\n")
def recurse(limit):
local_variable = "*" * limit
if limit <= 0:
show_stack()
return
recurse(limit - 1)
return local_variable
recurse(2)
这对调试递归调用时的错误非常有用。