检查 — 检查活动对象 — Python 文档

来自菜鸟教程
Python/docs/3.7/library/inspect
跳转至:导航、​搜索

inspect — 检查活动对象

源代码: :source:`Lib/inspect.py`



inspect 模块提供了几个有用的函数来帮助获取有关活动对象的信息,例如模块、类、方法、函数、回溯、框架对象和代码对象。 例如,它可以帮助您检查类的内容、检索方法的源代码、提取和格式化函数的参数列表,或者获取显示详细回溯所需的所有信息。

该模块提供四种主要服务:类型检查、获取源代码、检查类和函数以及检查解释器堆栈。

类型和成员

getmembers() 函数检索对象的成员,例如类或模块。 名称以“is”开头的函数主要作为 getmembers() 的第二个参数的方便选择。 它们还可以帮助您确定何时可以找到以下特殊属性:

类型 属性 描述
模块 __文档__ 文档字符串
__文件__ 文件名(缺少内置模块)
班级 __文档__ 文档字符串
__名称__ 定义此类的名称
__qualname__ 限定名
__模块__ 定义此类的模块的名称
方法 __文档__ 文档字符串
__名称__ 定义此方法的名称
__qualname__ 限定名
__func__ 包含方法实现的函数对象
__自己__ 此方法绑定到的实例,或 None
__模块__ 定义此方法的模块的名称
功能 __文档__ 文档字符串
__名称__ 定义此函数的名称
__qualname__ 限定名
__代码__ 包含编译函数的代码对象 bytecode
__默认值__ 位置或关键字参数的任何默认值的元组
__kwdefaults__ 仅关键字参数的任何默认值的映射
__全局变量__ 定义此函数的全局命名空间
__注释__ 参数名称到注释的映射; "return" 键保留用于返回注释。
__模块__ 定义此函数的模块的名称
追溯 tb_frame 此级别的框架对象
tb_lasti 字节码中最后尝试指令的索引
tb_lineno Python 源代码中的当前行号
tb_next 下一个内部回溯对象(由该级别调用)
框架 f_back 下一个外部框架对象(此框架的调用者)
f_builtins 这个框架看到的内置命名空间
代码 在此帧中执行的代码对象
f_globals 这个框架看到的全局命名空间
f_lasti 字节码中最后尝试指令的索引
f_lineno Python 源代码中的当前行号
f_locals 此框架看到的本地命名空间
f_trace 此帧的跟踪功能,或 None
代码 co_argcount 参数的数量(不包括仅关键字参数,* 或 ** 参数)
代码 原始编译字节码字符串
co_cellvars 单元变量名称的元组(由包含范围引用)
co_consts 字节码中使用的常量元组
文件名 在其中创建此代码对象的文件的名称
co_firstlineno Python 源代码中第一行的数量
co_flags CO_* 标志位图,在此处阅读更多 [[#inspect-module-co-flags|]]
co_lnotab 行号到字节码索引的编码映射
co_freevars 自由变量名称的元组(通过函数的闭包引用)
co_kwonlyargcount 仅关键字参数的数量(不包括 ** arg)
co_name 定义此代码对象的名称
co_names 局部变量名称元组
co_nlocals 局部变量的数量
co_stacksize 需要的虚拟机堆栈空间
co_varnames 参数名称和局部变量的元组
发电机 __名称__ 名称
__qualname__ 限定名
gi_frame 框架
gi_running 发电机在运行吗?
gi_code 代码
gi_yieldfrom yield fromNone 迭代的对象
协程 __名称__ 名称
__qualname__ 限定名
cr_await 正在等待的对象,或 None
cr_frame 框架
cr_running 协程在运行吗?
代码 代码
cr_origin 创建协程的位置,或 None。 见 sys.set_coroutine_origin_tracking_depth()
内置 __文档__ 文档字符串
__名称__ 此函数或方法的原始名称
__qualname__ 限定名
__自己__ 方法绑定到的实例,或 None

3.5 版更改: 为生成器添加 __qualname__gi_yieldfrom 属性。

生成器的 __name__ 属性现在从函数名称设置,而不是代码名称,现在可以修改。


3.7 版更改: 向协程添加 cr_origin 属性。


inspect.getmembers(object[, predicate])

在按名称排序的 (name, value) 对列表中返回对象的所有成员。 如果提供了可选的 predicate 参数,则仅包括谓词为其返回真值的成员。

笔记

getmembers() 仅当参数是类并且这些属性已在元类的自定义 __dir__() 中列出时,才会返回元类中定义的类属性。

inspect.getmodulename(path)

返回由文件 path 命名的模块的名称,不包括封闭包的名称。 根据 importlib.machinery.all_suffixes() 中的所有条目检查文件扩展名。 如果匹配,则返回最终路径组件并删除扩展名。 否则,返回 None

请注意,此函数 only 为实际 Python 模块返回一个有意义的名称 - 可能引用 Python 包的路径仍将返回 None

3.3 版本变化: 功能直接基于importlib

inspect.ismodule(object)
如果对象是模块,则返回 True
inspect.isclass(object)
如果对象是一个类,无论是内置的还是在 Python 代码中创建的,则返回 True
inspect.ismethod(object)
如果对象是用 Python 编写的绑定方法,则返回 True
inspect.isfunction(object)
如果对象是 Python 函数,则返回 True,其中包括由 lambda 表达式创建的函数。
inspect.isgeneratorfunction(object)
如果对象是 Python 生成器函数,则返回 True
inspect.isgenerator(object)
如果对象是生成器,则返回 True
inspect.iscoroutinefunction(object)

如果对象是 协程函数 (使用 async def 语法定义的函数),则返回 True

3.5 版中的新功能。

inspect.iscoroutine(object)

如果对象是由 async def 函数创建的 协程 ,则返回 True

3.5 版中的新功能。

inspect.isawaitable(object)

如果对象可以在 await 表达式中使用,则返回 True

也可用于区分基于生成器的协程和常规生成器:

def gen():
    yield
@types.coroutine
def gen_coro():
    yield

assert not isawaitable(gen())
assert isawaitable(gen_coro())

3.5 版中的新功能。

inspect.isasyncgenfunction(object)

如果对象是 异步生成器 函数,则返回 True,例如:

>>> async def agen():
...     yield 1
...
>>> inspect.isasyncgenfunction(agen)
True

3.6 版中的新功能。

inspect.isasyncgen(object)

如果对象是由 异步生成器 函数创建的 异步生成器迭代器 ,则返回 True

3.6 版中的新功能。

inspect.istraceback(object)
如果对象是回溯,则返回 True
inspect.isframe(object)
如果对象是框架,则返回 True
inspect.iscode(object)
如果对象是代码,则返回 True
inspect.isbuiltin(object)
如果对象是内置函数或绑定的内置方法,则返回 True
inspect.isroutine(object)
如果对象是用户定义的或内置的函数或方法,则返回 True
inspect.isabstract(object)
如果对象是抽象基类,则返回 True
inspect.ismethoddescriptor(object)

如果对象是方法描述符,则返回 True ]isbuiltin() 是真的。

例如,这适用于 int.__add__。 通过此测试的对象具有 __get__() 方法,但没有 __set__() 方法,但除此之外,属性集各不相同。 __name__ 属性通常是明智的,而 __doc__ 通常是明智的。

通过也通过其他测试之一的描述符实现的方法从 ismmethoddescriptor() 测试返回 False,这仅仅是因为其他测试承诺更多——例如,您可以依靠 [ X217X] 对象通过 ismmethod() 时的属性(等)。

inspect.isdatadescriptor(object)

如果对象是数据描述符,则返回 True

数据描述符同时具有 __get____set__ 方法。 示例是属性(在 Python 中定义)、getset 和成员。 后两者是在 C 中定义的,并且这些类型有更具体的测试可用,这在 Python 实现中是健壮的。 通常,数据描述符还将具有 __name____doc__ 属性(属性、getset 和成员具有这两个属性),但这并不能保证。

inspect.isgetsetdescriptor(object)
如果对象是 getset 描述符,则返回 True
inspect.ismemberdescriptor(object)
如果对象是成员描述符,则返回 True


检索源代码

inspect.getdoc(object)

获取对象的文档字符串,用 cleandoc() 清理。 如果未提供对象的文档字符串并且该对象是类、方法、属性或描述符,则从继承层次结构中检索文档字符串。

3.5 版更改: 文档字符串现在可以继承,如果没有被覆盖。

inspect.getcomments(object)
在单个字符串中返回紧接在对象源代码之前(对于类、函数或方法)或 Python 源文件顶部(如果对象是模块)的任何注释行。 如果对象的源代码不可用,则返回 None。 如果对象已在 C 或交互式 shell 中定义,则可能会发生这种情况。
inspect.getfile(object)
返回定义对象的(文本或二进制)文件的名称。 如果对象是内置模块、类或函数,这将失败并显示 TypeError
inspect.getmodule(object)
尝试猜测对象是在哪个模块中定义的。
inspect.getsourcefile(object)
返回定义对象的 Python 源文件的名称。 如果对象是内置模块、类或函数,这将失败并显示 TypeError
inspect.getsourcelines(object)

返回对象的源行列表和起始行号。 参数可以是模块、类、方法、函数、回溯、框架或代码对象。 源代码作为与对象对应的行列表返回,行号指示在原始源文件中找到第一行代码的位置。 如果无法检索源代码,则会引发 OSError

在 3.3 版更改:OSError 被引发而不是 IOError,现在是前者的别名。

inspect.getsource(object)

返回对象的源代码文本。 参数可以是模块、类、方法、函数、回溯、框架或代码对象。 源代码作为单个字符串返回。 如果无法检索源代码,则会引发 OSError

在 3.3 版更改:OSError 被引发而不是 IOError,现在是前者的别名。

inspect.cleandoc(doc)

清除缩进以与代码块对齐的文档字符串中的缩进。

从第一行中删除所有前导空格。 任何可以从第二行开始统一删除的前导空格都将被删除。 随后删除开头和结尾的空行。 此外,所有选项卡都扩展为空格。


使用 Signature 对象内省可调用对象

3.3 版中的新功能。


Signature 对象表示可调用对象的调用签名及其返回注释。 要检索 Signature 对象,请使用 signature() 函数。

inspect.signature(callable, \*, follow_wrapped=True)

为给定的 callable 返回一个 Signature 对象:

>>> from inspect import signature
>>> def foo(a, *, b:int, **kwargs):
...     pass

>>> sig = signature(foo)

>>> str(sig)
'(a, *, b:int, **kwargs)'

>>> str(sig.parameters['b'])
'b:int'

>>> sig.parameters['b'].annotation
<class 'int'>

接受范围广泛的 Python 可调用对象,从普通函数和类到 functools.partial() 对象。

如果无法提供签名,则引发 ValueError,如果不支持该类型的对象,则引发 TypeError

函数签名中的斜杠 (/) 表示它之前的参数仅是位置参数。 有关更多信息,请参阅 有关仅位置参数的常见问题解答条目

3.5 版新增:follow_wrapped 参数。 通过 False 获得 callable 的签名(callable.__wrapped__ 将不会用于解包装饰的可调用对象。)

笔记

某些可调用对象在 Python 的某些实现中可能无法自省。 例如,在 CPython 中,C 中定义的一些内置函数不提供有关其参数的元数据。

class inspect.Signature(parameters=None, \*, return_annotation=Signature.empty)

Signature 对象表示函数的调用签名及其返回注释。 对于函数接受的每个参数,它在其 参数 集合中存储一个 Parameter 对象。

可选的 parameters 参数是一个 Parameter 对象的序列,它被验证以检查没有重名的参数,并且参数的顺序正确,即 首先是仅位置,然后是位置或关键字,并且具有默认值的参数跟随没有默认值的参数。

可选的 return_annotation 参数,可以是任意的 Python 对象,是可调用对象的“返回”注释。

签名对象是 不可变的 。 使用 Signature.replace() 制作修改后的副本。

3.5 版更改: 签名对象是可picklable 和hashable 的。

empty

一个特殊的类级别标记,用于指定没有返回注释。

parameters

参数名称到相应 Parameter 对象的有序映射。 参数以严格的定义顺序出现,包括仅限关键字的参数。

3.7 版更改:Python 仅明确保证自 3.7 版起保留仅关键字参数的声明顺序,尽管实际上该顺序一直保留在 Python 3 中。

return_annotation

可调用对象的“返回”注释。 如果可调用对象没有“返回”注释,则此属性设置为 Signature.empty

bind(*args, **kwargs)

创建从位置和关键字参数到参数的映射。 如果 *args**kwargs 与签名匹配,则返回 BoundArguments,或者引发 TypeError

bind_partial(*args, **kwargs)

Signature.bind() 的工作方式相同,但允许省略一些必需的参数(模仿 functools.partial() 行为。)返回 BoundArguments,如果传递的参数与签名不匹配,则引发 TypeError

replace(*[, parameters][, return_annotation])

基于调用替换的实例创建一个新的签名实例。 可以通过不同的 parameters 和/或 return_annotation 来覆盖基本签名的相应属性。 要从复制的签名中删除 return_annotation,请传入 Signature.empty

>>> def test(a, b):
...     pass
>>> sig = signature(test)
>>> new_sig = sig.replace(return_annotation="new return anno")
>>> str(new_sig)
"(a, b) -> 'new return anno'"
classmethod from_callable(obj, \*, follow_wrapped=True)

为给定的可调用对象 obj 返回一个 Signature(或其子类)对象。 通过 follow_wrapped=False 获得 obj 的签名,而无需解开其 __wrapped__ 链。

此方法简化了 Signature 的子类化:

class MySignature(Signature):
    pass
sig = MySignature.from_callable(min)
assert isinstance(sig, MySignature)

3.5 版中的新功能。

class inspect.Parameter(name, kind, \*, default=Parameter.empty, annotation=Parameter.empty)

参数对象是 不可变的 。 您可以使用 Parameter.replace() 创建修改后的副本,而不是修改 Parameter 对象。

3.5 版更改: 参数对象是可拾取和可散列的。

empty

一个特殊的类级别标记,用于指定默认值和注释的缺失。

name

作为字符串的参数名称。 该名称必须是有效的 Python 标识符。

default

参数的默认值。 如果参数没有默认值,则该属性设置为Parameter.empty

annotation

参数的注释。 如果参数没有注释,则该属性设置为Parameter.empty

kind

描述如何将参数值绑定到参数。 可能的值(可通过 Parameter 访问,如 Parameter.KEYWORD_ONLY):

名称

意义

POSITIONAL_ONLY

值必须作为位置参数提供。

Python 没有用于定义仅位置参数的明确语法,但许多内置和扩展模块函数(尤其是那些只接受一两个参数的函数)接受它们。

POSITIONAL_OR_KEYWORD

值可以作为关键字或位置参数提供(这是在 Python 中实现的函数的标准绑定行为。)

VAR_POSITIONAL

未绑定到任何其他参数的位置参数元组。 这对应于 Python 函数定义中的 *args 参数。

KEYWORD_ONLY

值必须作为关键字参数提供。 仅关键字参数是出现在 Python 函数定义中 **args 条目之后的参数。

VAR_KEYWORD

未绑定到任何其他参数的关键字参数的字典。 这对应于 Python 函数定义中的 **kwargs 参数。

示例:打印所有没有默认值的仅关键字参数:

>>> def foo(a, b, *, c, d=10):
...     pass

>>> sig = signature(foo)
>>> for param in sig.parameters.values():
...     if (param.kind == param.KEYWORD_ONLY and
...                        param.default is param.empty):
...         print('Parameter:', param)
Parameter: c
replace(*[, name][, kind][, default][, annotation])

基于被替换的实例创建一个新的 Parameter 实例被调用。 要覆盖 Parameter 属性,请传递相应的参数。 要从参数中删除默认值或/和注释,请传递 Parameter.empty

>>> from inspect import Parameter
>>> param = Parameter('foo', Parameter.KEYWORD_ONLY, default=42)
>>> str(param)
'foo=42'

>>> str(param.replace()) # Will create a shallow copy of 'param'
'foo=42'

>>> str(param.replace(default=Parameter.empty, annotation='spam'))
"foo:'spam'"

3.4 版更改:在 Python 3.3 中,如果 kind 设置为 POSITIONAL_ONLY,则允许将 name 设置为 None ]。 这不再被允许。

class inspect.BoundArguments

Signature.bind()Signature.bind_partial() 调用的结果。 保存参数到函数参数的映射。

arguments

参数名称到参数值的有序、可变映射 (collections.OrderedDict)。 仅包含明确绑定的参数。 arguments 的变化将反映在 argskwargs 中。

应与 Signature.parameters 结合用于任何参数处理目的。

笔记

跳过 Signature.bind()Signature.bind_partial() 依赖于默认值的参数。 但是,如果需要,请使用 BoundArguments.apply_defaults() 添加它们。

args

位置参数值的元组。 从 arguments 属性动态计算。

kwargs

关键字参数值的字典。 从 arguments 属性动态计算。

signature

对父 Signature 对象的引用。

apply_defaults()

为缺少的参数设置默认值。

对于可变位置参数 (*args),默认值是一个空元组。

对于可变关键字参数 (**kwargs),默认值为空字典。

>>> def foo(a, b='ham', *args): pass
>>> ba = inspect.signature(foo).bind('spam')
>>> ba.apply_defaults()
>>> ba.arguments
OrderedDict([('a', 'spam'), ('b', 'ham'), ('args', ())])

3.5 版中的新功能。

argskwargs 属性可用于调用函数:

def test(a, *, b):
    ...

sig = signature(test)
ba = sig.bind(10, b=20)
test(*ba.args, **ba.kwargs)

也可以看看

PEP 362 - 函数签名对象。
详细的规范、实现细节和示例。


类和函数

inspect.getclasstree(classes, unique=False)
将给定的类列表排列成嵌套列表的层次结构。 在嵌套列表出现的地方,它包含从其条目紧接在列表之前的类派生的类。 每个条目都是一个 2 元组,包含一个类和一个其基类的元组。 如果 unique 参数为真,则给定列表中每个类的返回结构中只出现一个条目。 否则,使用多重继承的类及其后代将出现多次。
inspect.getargspec(func)

获取 Python 函数参数的名称和默认值。 返回一个名为 的元组 ArgSpec(args, varargs, keywords, defaults)args 是参数名称的列表。 varargskeywords*** 参数或 None 的名称。 defaults 是默认参数值的元组,如果没有默认参数,则为 None ; 如果此元组具有 n 元素,则它们对应于 args 中列出的最后一个 n 元素。

自 3.0 版起已弃用: 使用 getfullargspec() 用于更新的 API,该 API 通常是直接替换,但也正确处理函数注释和仅关键字参数。

或者,使用 signature()Signature Object,它们为可调用对象提供更结构化的内省 API。

inspect.getfullargspec(func)

获取 Python 函数参数的名称和默认值。 返回一个名为 的元组

FullArgSpec(args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations)

args 是位置参数名称的列表。 varargs* 参数的名称,如果不接受任意位置参数,则为 Nonevarkw** 参数的名称,如果不接受任意关键字参数,则为 Nonedefaults 是对应于最后一个 n 位置参数的默认参数值的 n 元组,或者 None 如果没有定义这样的默认值. kwonlyargs 是按声明顺序的仅关键字参数名称列表。 kwonlydefaults 是将参数名称从 kwonlyargs 映射到未提供参数时使用的默认值的字典。 annotations 是将参数名称映射到注释的字典。 特殊键 "return" 用于报告函数返回值注释(如果有)。

请注意,signature()Signature Object 为可调用的自省提供了推荐的 API,并支持扩展模块 API 中有时会遇到的其他行为(如仅位置参数)。 保留此函数主要用于需要保持与 Python 2 inspect 模块 API 兼容的代码。

3.4 版本更改:此函数现在基于 signature(),但仍忽略 __wrapped__ 属性并在绑定的签名输出中包含已绑定的第一个参数方法。

在 3.6 版中更改:此方法以前被记录为已弃用,以支持 Python 3.5 中的 signature(),但该决定已被撤销,以恢复明确支持的标准接口从旧的 getargspec() API 迁移的单源 Python 2/3 代码。

3.7 版更改:Python 仅明确保证自 3.7 版起保留仅关键字参数的声明顺序,尽管实际上该顺序一直保留在 Python 3 中。

inspect.getargvalues(frame)

获取有关传递到特定框架的参数的信息。 返回一个名为 的元组 ArgInfo(args, varargs, keywords, locals)args 是参数名称的列表。 varargskeywords*** 参数或 None 的名称。 locals 是给定帧的局部字典。

笔记

此函数在 Python 3.5 中无意中被标记为已弃用。

inspect.formatargspec(args[, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations[, formatarg, formatvarargs, formatvarkw, formatvalue, formatreturns, formatannotations]])

根据 getfullargspec() 返回的值格式化一个漂亮的参数规范。

前七个参数是 (args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations)。

其他六个参数是被调用以将参数名称、* 参数名称、** 参数名称、默认值、返回注释和单个注释分别转换为字符串的函数。

例如:

>>> from inspect import formatargspec, getfullargspec
>>> def f(a: int, b: float):
...     pass
...
>>> formatargspec(*getfullargspec(f))
'(a: int, b: float)'

自 3.5 版起已弃用: 使用 signature()Signature Object,它们为可调用对象提供了更好的内省 API。

inspect.formatargvalues(args[, varargs, varkw, locals, formatarg, formatvarargs, formatvarkw, formatvalue])

根据 getargvalues() 返回的四个值格式化一个漂亮的参数规范。 format* 参数是相应的可选格式化函数,它们被调用以将名称和值转换为字符串。

笔记

此函数在 Python 3.5 中无意中被标记为已弃用。

inspect.getmro(cls)
按方法解析顺序返回类 cls 的基类的元组,包括 cls。 在这个元组中没有类出现不止一次。 请注意,方法解析顺序取决于 cls 的类型。 除非使用非常特殊的用户定义元类型,否则 cls 将是元组的第一个元素。
inspect.getcallargs(func, *args, **kwds)

argskwds 绑定到 Python 函数或方法 func 的参数名称,就好像它被它们一起调用一样。 对于绑定方法,还将第一个参数(通常命名为 self)绑定到关联的实例。 返回一个字典,将参数名称(包括 *** 参数的名称,如果有的话)映射到 args 和 kwds[ X165X]。 在错误地调用 func 的情况下,即 每当 func(*args, **kwds) 由于签名不兼容而引发异常时,都会引发相同类型和相同或相似消息的异常。 例如:

>>> from inspect import getcallargs
>>> def f(a, b=1, *pos, **named):
...     pass
>>> getcallargs(f, 1, 2, 3) == {'a': 1, 'named': {}, 'b': 2, 'pos': (3,)}
True
>>> getcallargs(f, a=2, x=4) == {'a': 2, 'named': {'x': 4}, 'b': 1, 'pos': ()}
True
>>> getcallargs(f)
Traceback (most recent call last):
...
TypeError: f() missing 1 required positional argument: 'a'

3.2 版中的新功能。

自 3.5 版起已弃用: 使用 Signature.bind()Signature.bind_partial() 代替。

inspect.getclosurevars(func)

获取 Python 函数或方法 func 中的外部名称引用到它们当前值的映射。 返回一个名为 的元组 ClosureVars(nonlocals, globals, builtins, unbound)nonlocals 将引用名称映射到词法闭包变量,globals 映射到函数的模块全局变量,而 builtins 映射到函数体可见的内置函数。 unbound 是在给定当前模块全局变量和内置函数的情况下根本无法解析的函数中引用的一组名称。

如果 func 不是 Python 函数或方法,则会引发 TypeError

3.3 版中的新功能。

inspect.unwrap(func, *, stop=None)

获取由 func 包装的对象。 它遵循 __wrapped__ 属性链,返回链中的最后一个对象。

stop 是一个可选回调,接受包装链中的对象作为其唯一参数,如果回调返回真值,则允许提前终止解包。 如果回调从不返回真值,则链中的最后一个对象将照常返回。 例如,如果链中的任何对象定义了 __signature__ 属性,则 signature() 使用它来停止展开。

如果遇到循环,则会引发 ValueError

3.4 版中的新功能。


解释器栈

当以下函数返回“帧记录”时,每条记录都是一个名为 的元组 FrameInfo(frame, filename, lineno, function, code_context, index)。 元组包含框架对象、文件名、当前行的行号、函数名、源代码中的上下文行列表以及该列表中当前行的索引。

3.5 版更改: 返回命名元组而不是元组。


笔记

保持对帧对象的引用(如在帧记录这些函数返回的第一个元素中找到)可能会导致您的程序创建引用循环。 一旦创建了引用循环,即使启用了 Python 的可选循环检测器,可以从形成循环的对象访问的所有对象的生命周期也会变得更长。 如果必须创建这样的循环,重要的是确保它们被明确破坏以避免对象的延迟破坏和内存消耗增加。

尽管循环检测器会捕捉到这些,但可以通过删除 finally 子句中的循环来确定帧(和局部变量)的破坏。 如果在编译 Python 或使用 gc.disable() 时禁用循环检测器,这也很重要。 例如:

def handle_stackframe_without_leak():
    frame = inspect.currentframe()
    try:
        # do something with the frame
    finally:
        del frame

如果您想保留框架(例如稍后打印回溯),您还可以使用 frame.clear() 方法中断引用循环。


大多数这些函数支持的可选 context 参数指定要返回的上下文行数,这些行以当前行为中心。

inspect.getframeinfo(frame, context=1)
获取有关框架或回溯对象的信息。 返回一个名为 的元组 Traceback(filename, lineno, function, code_context, index)
inspect.getouterframes(frame, context=1)

获取一个框架和所有外部框架的框架记录列表。 这些帧代表导致创建的调用。 返回列表中的第一个条目代表 frame; 最后一个条目代表 frame 堆栈上的最外层调用。

在 3.5 版更改: 返回 命名元组 FrameInfo(frame, filename, lineno, function, code_context, index) 的列表。

inspect.getinnerframes(traceback, context=1)

获取回溯帧和所有内部帧的帧记录列表。 这些帧表示由 引起的调用。 列表中的第一个条目代表 traceback; 最后一个条目表示引发异常的位置。

在 3.5 版更改: 返回 命名元组 FrameInfo(frame, filename, lineno, function, code_context, index) 的列表。

inspect.currentframe()
返回调用者堆栈帧的帧对象。
inspect.stack(context=1)

返回调用者堆栈的帧记录列表。 返回列表中的第一个条目代表调用者; 最后一个条目代表堆栈上最外层的调用。

在 3.5 版更改: 返回 命名元组 FrameInfo(frame, filename, lineno, function, code_context, index) 的列表。

inspect.trace(context=1)

返回当前帧和引发当前正在处理的异常的帧之间堆栈的帧记录列表。 列表中的第一个条目代表调用者; 最后一个条目表示引发异常的位置。

在 3.5 版更改: 返回 命名元组 FrameInfo(frame, filename, lineno, function, code_context, index) 的列表。


静态获取属性

getattr()hasattr() 都可以在获取或检查属性存在时触发代码执行。 描述符,如属性,将被调用,__getattr__()__getattribute__() 可能被调用。

对于需要被动内省的情况,如文档工具,这可能不方便。 getattr_static()getattr() 具有相同的签名,但避免在获取属性时执行代码。

inspect.getattr_static(obj, attr, default=None)

通过描述符协议 __getattr__()__getattribute__() 在不触发动态查找的情况下检索属性。

注意:此函数可能无法检索 getattr 可以获取的所有属性(例如动态创建的属性),并且可能会找到 getattr 不能获取的属性(例如引发 AttributeError 的描述符)。 它还可以返回描述符对象而不是实例成员。

如果实例 __dict__ 被另一个成员(例如属性)隐藏,则此函数将无法找到实例成员。

3.2 版中的新功能。

getattr_static() 不解析描述符,例如在 C 中实现的对象上的槽描述符或 getset 描述符。 返回描述符对象而不是底层属性。

您可以使用如下代码处理这些问题。 请注意,对于调用这些的任意 getset 描述符可能会触发代码执行:

# example code for resolving the builtin descriptor types
class _foo:
    __slots__ = ['foo']

slot_descriptor = type(_foo.foo)
getset_descriptor = type(type(open(__file__)).name)
wrapper_descriptor = type(str.__dict__['__add__'])
descriptor_types = (slot_descriptor, getset_descriptor, wrapper_descriptor)

result = getattr_static(some_object, 'foo')
if type(result) in descriptor_types:
    try:
        result = result.__get__()
    except AttributeError:
        # descriptors can raise AttributeError to
        # indicate there is no underlying value
        # in which case the descriptor itself will
        # have to do
        pass

生成器和协程的当前状态

在实现协程调度程序和生成器的其他高级用途时,确定生成器是当前正在执行、正在等待启动、恢复或执行还是已经终止是很有用的。 getgeneratorstate() 允许轻松确定生成器的当前状态。

inspect.getgeneratorstate(generator)

获取生成器迭代器的当前状态。

可能的状态是:
  • GEN_CREATED:等待开始执行。

  • GEN_RUNNING:当前由解释器执行。

  • GEN_SUSPENDED:当前暂停在一个产量表达式。

  • GEN_CLOSED:执行已完成。

3.2 版中的新功能。

inspect.getcoroutinestate(coroutine)

获取协程对象的当前状态。 该函数旨在与 async def 函数创建的协程对象一起使用,但将接受具有 cr_runningcr_frame 属性的任何类似协程的对象。

可能的状态是:
  • CORO_CREATED:等待开始执行。

  • CORO_RUNNING:当前由解释器执行。

  • CORO_SUSPENDED:当前暂停在等待表达式。

  • CORO_CLOSED:执行已完成。

3.5 版中的新功能。

还可以查询生成器当前的内部状态。 这主要用于测试目的,以确保内部状态按预期更新:

inspect.getgeneratorlocals(generator)

获取 generator 中实时局部变量到它们当前值的映射。 返回一个从变量名映射到值的字典。 这相当于在生成器的主体中调用 locals(),并且所有相同的警告都适用。

如果 generator 是当前没有关联框架的 generator,则返回一个空字典。 如果 generator 不是 Python 生成器对象,则会引发 TypeError

3.3 版中的新功能。

inspect.getcoroutinelocals(coroutine)

此函数类似于 getgeneratorlocals(),但适用于由 async def 函数创建的协程对象。

3.5 版中的新功能。


代码对象位标志

Python 代码对象有一个 co_flags 属性,它是以下标志的位图:

inspect.CO_OPTIMIZED
代码对象经过优化,使用快速本地变量。
inspect.CO_NEWLOCALS
如果设置,则在执行代码对象时将为帧的 f_locals 创建一个新的字典。
inspect.CO_VARARGS
代码对象有一个可变的位置参数(*args-like)。
inspect.CO_VARKEYWORDS
代码对象有一个变量关键字参数(**kwargs-like)。
inspect.CO_NESTED
当代码对象是嵌套函数时设置该标志。
inspect.CO_GENERATOR
当代码对象是生成器函数时设置标志,即 执行代码对象时返回生成器对象。
inspect.CO_NOFREE
如果没有自由变量或单元变量,则设置该标志。
inspect.CO_COROUTINE

当代码对象是协程函数时设置该标志。 当代码对象被执行时,它返回一个协程对象。 有关更多详细信息,请参阅 PEP 492

3.5 版中的新功能。

inspect.CO_ITERABLE_COROUTINE

该标志用于将生成器转换为基于生成器的协程。 带有这个标志的生成器对象可以用在 await 表达式中,并且可以 yield from 协程对象。 有关更多详细信息,请参阅 PEP 492

3.5 版中的新功能。

inspect.CO_ASYNC_GENERATOR

当代码对象是异步生成器函数时设置该标志。 当代码对象被执行时,它返回一个异步生成器对象。 有关更多详细信息,请参阅 PEP 525

3.6 版中的新功能。

笔记

这些标志特定于 CPython,可能未在其他 Python 实现中定义。 此外,这些标志是一个实现细节,可以在未来的 Python 版本中删除或弃用。 建议使用来自 inspect 模块的公共 API 来满足任何内省需求。


命令行界面

inspect 模块还提供了来自命令行的基本自省功能。

默认情况下,接受模块的名称并打印该模块的源代码。 模块中的类或函数可以通过附加冒号和目标对象的限定名称来打印。

--details
打印有关指定对象的信息而不是源代码