inspect --- 检查对象

原始碼:Lib/inspect.py


inspect 模块提供了一些有用的函数帮助获取对象的信息,例如模块、类、方法、函数、回溯、帧对象以及代码对象。例如它可以帮助你检查类的内容,获取某个方法的源代码,取得并格式化某个函数的参数列表,或者获取你需要显示的回溯的详细信息。

该模块提供了4种主要的功能:类型检查、获取源代码、检查类与函数、检查解释器的调用堆栈。

类型和成员

getmembers() 函数获取对象如类或模块的成员。 名称以“is”打头的函数主要是作为传给 getmembers() 的第二个参数的便捷选项提供的。 它们还可帮助你确定你是否能找到下列特殊属性(请参阅 导入相关的模块属性 了解有关模块属性的详情):

类型

屬性

描述

class

__doc__

文档字符串

__name__

类定义时所使用的名称

__qualname__

qualified name -- 限定名称

__module__

该类型被定义时所在的模块的名称

method -- 方法

__doc__

文档字符串

__name__

该方法定义时所使用的名称

__qualname__

qualified name -- 限定名称

__func__

实现该方法的函数对象

__self__

该方法被绑定的实例,若没有绑定则为 None

__module__

定义此方法的模块的名称

函式

__doc__

文档字符串

__name__

用于定义此函数的名称

__qualname__

qualified name -- 限定名称

__code__

包含已编译函数的代码对象 bytecode

__defaults__

所有位置或关键字参数的默认值的元组

__kwdefaults__

保存仅关键字参数的所有默认值的映射

__globals__

此函数定义所在的全局命名空间

__builtins__

builtins 命名空间

__annotations__

参数名称到注解的映射;保留键 "return" 用于返回值注解。

__module__

此函数定义所在的模块名称

traceback

tb_frame

此层的帧对象

tb_lasti

在字节码中最后尝试的指令的索引

tb_lineno

当前行在 Python 源代码中的行号

tb_next

下一个内部回溯对象(由本层调用)

frame -- 帧

f_back

下一个外部帧对象(此帧的调用者)

f_builtins

此帧执行时所在的 builtins 命名空间

f_code

在此帧中执行的代码对象

f_globals

此帧执行时所在的全局命名空间

f_lasti

在字节码中最后尝试的指令的索引

f_lineno

当前行在 Python 源代码中的行号

f_locals

此帧所看到的局部命名空间

f_trace

此帧的追踪函数,或 None

code(程式碼)

co_argcount

参数数量(不包括仅关键字参数、* 或 ** 参数)

co_code

字符串形式的原始字节码

co_cellvars

单元变量名称的元组(通过包含作用域引用)

co_consts

字节码中使用的常量元组

co_filename

创建此代码对象的文件的名称

co_firstlineno

第一行在Python源代码中的行号

co_flags

CO_* 标志的位图,详见 此处

co_lnotab

编码的行号到字节码索引的映射

co_freevars

自由变量的名字组成的元组(通过函数闭包引用)

co_posonlyargcount

仅限位置参数的数量

co_kwonlyargcount

仅限关键字参数的数量(不包括 ** 参数)

co_name

定义此代码对象的名称

co_qualname

定义此代码对象的完整限定名称

co_names

除参数和函数局部变量之外的名称元组

co_nlocals

局部变量的数量

co_stacksize

需要虚拟机堆栈空间

co_varnames

参数名和局部变量的元组

generator -- 生成器

__name__

name

__qualname__

qualified name -- 限定名称

gi_frame

frame -- 帧

gi_running

生成器在运行吗?

gi_code

code(程式碼)

gi_yieldfrom

通过 yield from``迭代的对象,或``None

coroutine -- 协程

__name__

name

__qualname__

qualified name -- 限定名称

cr_await

正在等待的对象,或 None

cr_frame

frame -- 帧

cr_running

这个协程正在运行吗?

cr_code

code(程式碼)

cr_origin

协程被创建的位置,或 None。参见 sys.set_coroutine_origin_tracking_depth()

builtin

__doc__

文档字符串

__name__

此函数或方法的原始名称

__qualname__

qualified name -- 限定名称

__self__

方法绑定到的实例,或 None

在 3.5 版的變更: 为生成器添加 __qualname__gi_yieldfrom 属性。

生成器的 __name__ 属性现在由函数名称设置,而不是代码对象名称,并且现在可以被修改。

在 3.7 版的變更: 为协程添加 cr_origin 属性。

在 3.10 版的變更: 为函数添加 __builtins__ 属性。

inspect.getmembers(object[, predicate])

返回一个对象上的所有成员,组成以 (名称, 值) 对为元素的列表,按名称排序。如果提供了可选的 predicate 参数(会对每个成员的 对象进行一次调用),则仅包含该断言为真的成员。

備註

当参数是一个类且这些属性在元类的自定义方法 __dir__() 中列出时 getmembers() 将只返回在元类中定义的类属性。

inspect.getmembers_static(object[, predicate])

将一个对象的所有成员作为由 (name, value) 对组成并按名称排序的列表返回而不触发通过描述器协议 __getattr__ 或 __getattribute__ 执行的动态查找。 或是作为可选项,只返回满足给定预期的成员。

備註

getmembers_static() 可能无法获得 getmembers 所能获取的所有成员(如动态创建的属性)并且可能会找到一些 getmembers 所不能找到的成员(如会引发 AttributeError 的描述器)。 在某些情况下它还能返回描述器对象而不是实例成员。

在 3.11 版新加入.

inspect.getmodulename(path)

返回由文件名 path 表示的模块名字,但不包括外层的包名。文件扩展名会检查是否在 importlib.machinery.all_suffixes() 列出的条目中。如果符合,则文件路径的最后一个组成部分会去掉后缀名后被返回;否则返回 None

值得注意的是,这个函数 返回可以作为 Python 模块的名字,而有可能指向一个 Python 包的路径仍然会返回 None

在 3.3 版的變更: 该函数直接基于 importlib

inspect.ismodule(object)

当该对象是一个模块时返回 True

inspect.isclass(object)

当该对象是一个类时返回 True,无论是内置类或者 Python 代码中定义的类。

inspect.ismethod(object)

当该对象是一个 Python 写成的绑定方法时返回 True

inspect.isfunction(object)

当该对象是一个 Python 函数时(包括使用 lambda 表达式创造的函数),返回 True

inspect.isgeneratorfunction(object)

当该对象是一个 Python 生成器函数时返回 True

在 3.8 版的變更: 对于使用 functools.partial() 封装的函数,如果被封装的函数是一个 Python 生成器函数,现在也会返回 True

inspect.isgenerator(object)

当该对象是一个生成器时返回 True

inspect.iscoroutinefunction(object)

Return True if the object is a coroutine function (a function defined with an async def syntax).

在 3.5 版新加入.

在 3.8 版的變更: 对于使用 functools.partial() 封装的函数,如果被封装的函数是一个 协程函数 ,现在也会返回 True

inspect.iscoroutine(object)

当该对象是一个由 async def 函数创建的 协程 时返回 True

在 3.5 版新加入.

inspect.isawaitable(object)

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

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

import types

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

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

在 3.5 版新加入.

inspect.isasyncgenfunction(object)

如果对象是一个 asynchronous generator 函数则返回 True,例如:

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

在 3.6 版新加入.

在 3.8 版的變更: 对于使用 functools.partial() 封装的函数,如果被封装的函数是一个 异步生成器 ,现在也会返回 True

inspect.isasyncgen(object)

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

在 3.6 版新加入.

inspect.istraceback(object)

如果该对象是一个回溯则返回 True

inspect.isframe(object)

如果该对象是一个帧对象则返回 True

inspect.iscode(object)

如果该对象是一个代码对象则返回 True

inspect.isbuiltin(object)

如果该对象是一个内置函数或一个绑定的内置方法,则返回 True

inspect.ismethodwrapper(object)

如果对象类型为 MethodWrapperType 则返回 True

这些是 MethodWrapperType 的实例,如 __str__(), __eq__()__repr__()

在 3.11 版新加入.

inspect.isroutine(object)

如果该对象是一个用户定义的或内置的函数或者方法,则返回 True

inspect.isabstract(object)

如果该对象是一个抽象基类则返回 True

inspect.ismethoddescriptor(object)

如果该对象是一个方法描述器,但 ismethod()isclass()isfunction()isbuiltin() 均不为真,则返回 True

例如,该函数对于 int.__add__ 为真。 一个通过此测试的对象可以有 __get__() 方法,但不能有 __set__() 方法,除此以外的属性集合是可变的。 一个 __name__ 属性通常是合理的,而 __doc__ 往往也是如此。

以描述器实现的能够通过其他某个测试的函数对于 ismethoddescriptor() 测试也会返回 False,这只是因为其他测试提供了更多保证 —— 比如,当一个对象通过 ismethod() 时你将能够使用 __func__ 等属性。

inspect.isdatadescriptor(object)

如果该对象是一个数据描述器则返回 True

数据描述器具有 __set____delete__ 方法。 例如特征属性(在 Python 中定义)、getset 和成员等。 后两者是在 C 中定义并且有针对这些类型的更具体的测试,它们在不同 Python 实现中均能保持健壮性。 通常,数据描述器还具有 __name____doc__ 属性(特征属性、getset 和成员都同时具有这些属性),但并不保证这一点。

inspect.isgetsetdescriptor(object)

如果该对象是一个 getset 描述器则返回 True

CPython 實作細節: getset 是在扩展模块中通过 PyGetSetDef 结构体定义的属性。对于不包含这种类型的 Python 实现,这个方法将永远返回 False

inspect.ismemberdescriptor(object)

如果该对象是一个成员描述器则返回 True

CPython 實作細節: 成员描述器是在扩展模块中通过 PyMemberDef 结构体定义的属性。对于不包含这种类型的 Python 实现,这个方法将永远返回 False

获取源代码

inspect.getdoc(object)

获取对象的文档字符串并通过 cleandoc() 进行清理。如果对象本身并未提供文档字符串并且这个对象是一个类、一个方法、一个特性或者一个描述器,将通过继承层次结构获取文档字符串。如果文档字符串无效或缺失,则返回 None

在 3.5 版的變更: 文档字符串没有被重写的话现在会被继承。

inspect.getcomments(object)

任意多行注释作为单一一个字符串返回。对于类、函数和方法,选取紧贴在该对象的源代码之前的注释;对于模块,选取 Python 源文件顶部的注释。如果对象的源代码不可获得,返回 None。这可能是因为对象是 C 语言中或者是在交互式命令行中定义的。

inspect.getfile(object)

返回定义了这个对象的文件名(包括文本文件或二进制文件)。如果该对象是一个内置模块、类或函数则会失败并引发一个 TypeError

inspect.getmodule(object)

尝试猜测一个对象是在哪个模块中定义的。 如果无法确定模块则返回 None

inspect.getsourcefile(object)

返回一个对象定义所在 Python 源文件的名称,如果无法获取源文件则返回 None。 如果对象是一个内置模块、类或函数则将失败并引发 TypeError

inspect.getsourcelines(object)

返回一个源代码行的列表和对象的起始行号。 参数可以是一个模块、类、方法、函数、回溯或者代码对象。 源代码将以与该对象所对应的行的列表的形式返回并且行号指明其中第一行代码出现在初始源文件的那个位置。 如果源代码无法被获取则会引发 OSError。 如果对象是一个内置模块、类或函数则会引发 TypeError

在 3.3 版的變更: 现在会引发 OSError 而不是 IOError,后者现在是前者的一个别名。

inspect.getsource(object)

返回对象的源代码文本。 参数可以是一个模块、类、方法、函数、回溯帧或代码对象。 源代码将以单个字符串的形式被返回。 如果源代码无法被获取则会引发 OSError。 如果对象是一个内置模块、类或函数则会引发 TypeError

在 3.3 版的變更: 现在会引发 OSError 而不是 IOError,后者现在是前者的一个别名。

inspect.cleandoc(doc)

清理文档字符串中为对齐当前代码块进行的缩进

第一行的所有前缀空白符会被移除。从第二行开始所有可以被统一去除的空白符也会被去除。之后,首尾的空白行也会被移除。同时,所有制表符会被展开到空格。

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

在 3.3 版新加入.

Signature 对象代表一个可调用对象的调用签名及其返回值标。 要获取一个 Signature 对象,可使用 signature() 函数。

inspect.signature(callable, *, follow_wrapped=True, globals=None, locals=None, eval_str=False)

返回一个给定 callableSignature 对象:

>>> 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() 对象。

对于使用字符化标注的模块中定义的对象 (from __future__ import annotations),signature() 会尝试使用 get_annotations() 自动地反字符串化这些标注。 globals, localseval_str 等形参会在解析标注时被传入 get_annotations();请参阅 get_annotations() 的文档获取如何使用这些形参的说明。

如果没有可提供的签名则会引发 ValueError,而如果对象类型不受支持则会引发 TypeError。 同时,如果标注被字符串化,并且 eval_str 不为假值,则在 get_annotations() 中调用 eval() 来反字符串化标注可能会引发任何种类的异常。

函数签名中的斜杠(/)表示在它之前的参数是仅限位置的。详见 编程常见问题中关于仅限位置参数的条目

在 3.5 版的變更: 添加了 follow_wrapped 形参。 传入 False 以获得特定 callable 的签名 (callable.__wrapped__ 将不会被用来解包被装饰的可调用对象。)

在 3.10 版的變更: 添加了 globals, localseval_str 形参。

備註

一些可调用对象可能在特定 Python 实现中无法被内省。例如,在 CPython 中,部分通过 C 语言定义的内置函数不提供关于其参数的元数据。

CPython 實作細節: If the passed object has a __signature__ attribute, we may use it to create the signature. The exact semantics are an implementation detail and are subject to unannounced changes. Consult the source code for current semantics.

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

Signature 对象表示一个函数的调用签名及其返回值标注。 对于函数所接受的每个形参它会在其 parameters 多项集中存储一个 Parameter 对象。

可选参数 parameters 是一个 Parameter 对象组成的序列,它会在之后被验证不存在名字重复的参数,并且参数处于正确的顺序,即仅限位置参数最前,之后紧接着可位置可关键字参数,并且有默认值参数在无默认值参数之前。

可选的 return_annotation 参数可以是任意 Python 对象。 它表示可调用对象的 "return" 标注。

Signature 对象是 不可变 对象。 使用 Signature.replace() 来创建修改后的副本。

在 3.5 版的變更: Signature 对象现在是可 pickle 且 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])

根据发起调用 replace() 的实例新建一个 Signature 实例。 可以通过传入不同的 parameters 和/或 return_annotation 来覆盖基类签名的相应特征属性。 要从拷贝的 Signature 中移除 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, globals=None, locals=None, eval_str=False)

返回给定的可调用对象 objSignature (或其子类)。

该方法简化了 Signature 的子类化操作:

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

其行为在其他方面都与 signature() 相同。

在 3.5 版新加入.

在 3.10 版的變更: 添加了 globals, localseval_str 形参。

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

Parameter 对象是 不可变 对象。 不要直接修改 Parameter 对象,请可以使用 Parameter.replace() 创建一个修改后的副本。

在 3.5 版的變更: 现在 Parameter 对象可以被 pickle 并且为 hashable

empty

该类的一个特殊标记来明确指出默认值和标注的缺失。

name

参数的名字字符串。这个名字必须是一个合法的 Python 标识符。

CPython 實作細節: CPython 会为用于实现推导式和生成器表达式的代码对象构造形如 .0 的隐式形参名。

在 3.6 版的變更: 这些形参名会被此模块公开为 implicit0 这样的名字。

default

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

annotation

该参数的标注。如果该参数没有标注,这个属性会被设置为 Parameter.empty

kind

描述参数值要如何绑定到形参。 可能的取值可通过 Parameter 获得 (如 Parameter.KEYWORD_ONLY),并支持比较与排序,基于以下顺序:

名稱

意義

POSITIONAL_ONLY

值必须以位置参数的方式提供。仅限位置参数是在函数定义中出现在 / 之前(如果有)的条目。

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
kind.description

描述 Parameter.kind 的枚举值。

在 3.8 版新加入.

示例:打印全部参数的描述:

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

>>> sig = signature(foo)
>>> for param in sig.parameters.values():
...     print(param.kind.description)
positional or keyword
positional or keyword
keyword-only
keyword-only
replace(*[, name][, kind][, default][, annotation])

根据发起调用 replace 的实例新建一个 Parameter 实例。 要覆盖一个 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 中 Parameter 对象在其 kind 被设为 POSITIONAL_ONLY 时允许将 name 设为 None。 现在已不再允许这样做。

class inspect.BoundArguments

调用 Signature.bind()Signature.bind_partial() 的结果。容纳实参到函数的形参的映射。

arguments

一个形参名到实参值的可变映射。仅包含显式绑定的参数。对 arguments 的修改会反映到 argskwargs 上。

应当在任何参数处理目的中与 Signature.parameters 结合使用。

備註

 Signature.bind()Signature.bind_partial() 中采用默认值的参数被跳过。然而,如果有需要的话,可以使用 BoundArguments.apply_defaults() 来添加它们。

在 3.9 版的變更:  arguments 现在的类型是 dict。之前,它的类型是 collections.OrderedDict

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
{'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)

将给定的类的列表组织成嵌套列表的层级结构。每当一个内层列表出现时,它包含的类均派生自紧接着该列表之前的条目的类。每个条目均是一个二元组,包含一个类和它的基类组成的元组。如果 unique 参数为真值,则给定列表中的每个类将恰有一个对应条目。否则,运用了多重继承的类和它们的后代将出现多次。

inspect.getfullargspec(func)

获取一个 Python 函数的形参的名字和默认值。将返回一个 具名元组

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

args 是一个位置参数的名字的列表。 varargs* 形参的名字或 None 表示不接受任意长位置参数时。 varkw** 参数的名字,或 None 表示不接受任意关键字参数。 defaults 是一个包含了默认参数值的 n 元组分别对应最后 n 个位置参数,或 None 则表示没有默认值。 kwonlyargs 是一个仅关键词参数列表,保持定义时的顺序。 kwonlydefaults 是一个字典映射自 kwonlyargs 中包含的形参名。 annotations 是一个字典,包含形参值到标注的映射。其中包含一个特殊的键 "return" 代表函数返回值的标注(如果有的话)。

注意: signature()Signature 对象 提供可调用对象内省更推荐的 API,并且支持扩展模块 API 中可能出现的额外的行为(比如仅限位置参数)。该函数被保留的主要原因是保持兼容 Python 2 的 inspect 模块 API。

在 3.4 版的變更: 该函数现在基于 signature() 但仍然忽略 __wrapped__ 属性,并且在签名中包含绑定方法中的第一个绑定参数。

在 3.6 版的變更: 该方法在 Python 3.5 中曾因 signature() 被文档归为弃用。但该决定已被推翻以恢复一个明确受支持的标准接口,以便运用一份源码通用 Python 2/3 间遗留的 getargspec() API 的迁移。

在 3.7 版的變更: Python 从 3.7 版起才显式地保证了它保持仅关键字参数的定义顺序,尽管实践上在 Python 3 中一直保持了这个顺序。

inspect.getargvalues(frame)

获取传入特定的帧的实参的信息。将返回一个 具名元组 ArgInfo(args, varargs, keywords, locals)args 是一个参数名字的列表。 varargskeyword*** 参数的名字或 Nonelocals 是给定的帧的局部环境字典。

備註

该函数因疏忽在 Python 3.5 中被错误地标记为弃用。

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) 绑定到关联的实例。 将返回一个字典,该字典会将参数名称(包括 *** 参数的名称,如果有的话)绑定到 argskwds 中的值。 对于不正确地发起调用 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 版新加入.

inspect.get_annotations(obj, *, globals=None, locals=None, eval_str=False)

计算一个对象的标注字典。

 obj 可以是一个可调用对象、类或模块。传入其他类型的对象将引发 TypeError

返回一个字典。 get_annotations() 每次调用均返回一个新的字典;对同一个对象调用两次将获得两个不同但相等的字典。

该函数帮助你处理若干细节:

  • 如果 eval_str 为真, str 类型的值将会通过 eval() 来反字符串化。这被设计用于字符串化标注(from __future__ import annotations)。

  • 如果 obj 不包含一个标注字典,返回一个空字典。(函数和方法永远包含一个标注字典;类、模块和其他类型的可调用对象则可能没有。)

  • 对于类,忽略继承而来的标注。如果一个类不包含自己的标注字典,返回一个空字典。

  • 因安全原因,所有对于对象成员和字典值的访问将通过 getattr()dict.get() 完成。

  • 请确保始终、始终、始终返回一个新创建的字典。

eval_str 控制 str 类型的值是否应该替换为对其调用 eval() 的结果:

  • 如果 eval_str 为真, eval() 会被调用于 str 类型。(注意 get_annotations 并不捕获异常;如果 eval() 返回一个错误,它会将栈展开跳过 get_annotations 调用。)

  • 如果 eval_str 为假(默认值), str 类型的值将不会被改变。

globalslocals 会被直接传入函数 eval(),详见 eval() 的文档。如果 globals 或者 localsNone,则改函数视 type(obj) 而定,可能将相应的值替换为一个上下文有关的默认值。

  • 如果 obj 是一个模块, globals 默认为 obj.__dict__

  • 如果 obj 是一个类, globals 默认值为 sys.modules[obj.__module__].__dict__ 并且 locals 默认值为 obj 的类命名空间。

  • 如果 obj 是一个可调用对象,则 globals 默认为 obj.__globals__,而如果 obj 是一个包装函数 (使用了 functools.update_wrapper()) 则它会先打开包装。

调用 get_annotations 是获取任何对象的标注字典的最佳实践。关于标注的最佳实践的更多信息,参见 对象注解属性的最佳实践

在 3.10 版新加入.

解释器栈

下列函数有些将返回 FrameInfo 对象。 出于向下兼容性考虑这些对象允许在所有属性上执行元组类操作但 positions 除外。 此行为已被弃用并可能会在未来被移除。

class inspect.FrameInfo
frame

记录所对应的 帧对象

filename

关联到由此记录所对应的帧对象所执行的代码的文件名称。

lineno

关联到由此记录所对应的帧对象所执行的代码的当前行的行号。

function

由此记录所对应的帧所执行的函数的名称。

code_context

来自由此记录所对应的帧所执行的源代码的上下文行组成的列表。

index

code_context 列表中执行的当前行的索引号。

positions

包含关联到由此记录所对应的指令的起始行号,结束行号,起始列偏移量和结束列偏移量的 dis.Positions 对象。

在 3.5 版的變更: 返回一个 named tuple 而非 tuple

在 3.11 版的變更: FrameInfo 现在是一个类实例(以便与之前的 named tuple 保持向下兼容)。

class inspect.Traceback
filename

关联到由此回溯所对应的帧所执行的代码的文件名称。

lineno

关联到由此回溯所对应的帧所执行的代码的当前行的行号。

function

由此回溯所对应的帧所执行的函数的名称。

code_context

来自由此回溯所对应的帧所执行的源代码的上下文行组成的列表。

index

code_context 列表中执行的当前行的索引号。

positions

包含关联到此回溯所对应的帧所执行的指令的起始行号,结束行号,起始列偏移量和结束列偏移量的 dis.Positions 对象。

在 3.11 版的變更: Traceback 现在是一个类实例(以便与之前的 named tuple 保持向下兼容)。

備註

保留帧对象的引用(可见于这些函数返回的帧记录的第一个元素)会导致你的程序产生循环引用。每当一个循环引用被创建,所有可从产生循环的对象访问的对象的生命周期将会被大幅度延长,即便 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 对象。

在 3.11 版的變更: 将返回一个 Traceback 对象而非具名元组。

inspect.getouterframes(frame, context=1)

获取某个帧及其所有外部帧的 FrameInfo 对象的列表。 这些帧代表导致 frame 被创建的一系列调用。 返回的列中的第一个条目代表 frame;最后一个条目代表在 frame 的栈上的最外层调用。

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

在 3.11 版的變更: 将返回一个 FrameInfo 对象的列表。

inspect.getinnerframes(traceback, context=1)

获取一个回溯所在的帧及其所有内部帧的 FrameInfo 对象的列表。 这些帧代表作为 frame 的后续所执行的调用。 列表中的第一个条目代表 traceback;最后一个条目代表引发异常的位置。

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

在 3.11 版的變更: 将返回一个 FrameInfo 对象的列表。

inspect.currentframe()

返回调用者的栈帧对应的帧对象。

CPython 實作細節: 该函数依赖于 Python 解释器对于栈帧的支持,这并非在 Python 的所有实现中被保证。该函数在不支持Python 栈帧的实现中运行会返回 None

inspect.stack(context=1)

返回调用者的栈的 FrameInfo 对象的列表。 返回的列表中的第一个条目代表调用者;最后一个条目代表栈上的最外层调用。

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

在 3.11 版的變更: 将返回一个 FrameInfo 对象的列表。

inspect.trace(context=1)

返回介于当前帧和引发了当前正在处理的异常所在的帧之间的栈的 FrameInfo 对象的列表。 列表中的第一个条目代表调用者;最后一个条目代表引发异常的位置。

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

在 3.11 版的變更: 将返回一个 FrameInfo 对象的列表。

静态地获取属性

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

Current State of Generators and Coroutines

当实现协程调度器或其他更高级的生成器用途时,判断一个生成器是正在执行、等待启动或继续或执行,又或者已经被终止是非常有用的。 getgeneratorstate() 允许方便地判断一个生成器的当前状态。

inspect.getgeneratorstate(generator)

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

可能的状态是:

  • GEN_CREATED:等待开始执行。

  • GEN_RUNNING:正在被解释器执行。

  • GEN_SUSPENDED:当前挂起于一个 yield 表达式。

  • GEN_CLOSED:执行已经完成。

在 3.2 版新加入.

inspect.getcoroutinestate(coroutine)

获取协程对象的当前状态。该函数设计为用于使用 async def 函数创建的协程函数,但也能接受任何包括 cr_runningcr_frame 的类似协程的对象。

可能的状态是:

  • CORO_CREATED:等待开始执行。

  • CORO_RUNNING:当前正在被解释器执行。

  • CORO_SUSPENDED:当前挂起于一个 await 表达式。

  • CORO_CLOSED:执行已经完成。

在 3.5 版新加入.

生成器当前的内部状态也可以被查询。这通常在测试目的中最为有用,来保证内部状态如预期一样被更新:

inspect.getgeneratorlocals(generator)

获取 generator 里的实时局部变量到当前值的映射。返回一个由名字映射到值的字典。这与在生成器的主体内调用 locals() 是等效的,并且相同的警告也适用。

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

CPython 實作細節: 该函数依赖于生成器为内省暴露一个 Python 栈帧,这并非在 Python 的所有实现中被保证。在这种情况下,该函数将永远返回一个空字典。

在 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)。

inspect.CO_VARKEYWORDS

代码对象拥有一个可变关键字形参 (类似 **kwrags)。

inspect.CO_NESTED

该标志当代码对象是一个嵌套函数时被置位。

inspect.CO_GENERATOR

当代码对象是一个生成器函数,即调用时会返回一个生成器对象,则该标志被置位。

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

打印特定对象的信息而非源码。