检查 — 检查活动对象 — Python 文档
inspect — 检查活动对象
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_posonlyargcount | 仅位置参数的数量 | |
co_kwonlyargcount | 仅关键字参数的数量(不包括 ** arg) | |
co_name | 定义此代码对象的名称 | |
co_names | 局部变量名称元组 | |
co_nlocals | 局部变量的数量 | |
co_stacksize | 需要的虚拟机堆栈空间 | |
co_varnames | 参数名称和局部变量的元组 | |
发电机 | __姓名__ | 姓名 |
__qualname__ | 限定名 | |
gi_frame | 框架 | |
gi_running | 发电机在运行吗? | |
gi_code | 代码 | |
gi_yieldfrom | 由 yield from 或 None 迭代的对象
| |
协程 | __姓名__ | 姓名 |
__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
属性。
3.10 版更改: 为函数添加 __builtins__
属性。
- inspect.getmembers(object[, predicate])
在按名称排序的
(name, value)
对列表中返回对象的所有成员。 如果提供了可选的 predicate 参数(将使用每个成员的value
对象调用),则仅包含谓词为其返回真值的成员。笔记
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
。3.8 版更改: 包裹在 functools.partial() 中的函数现在返回
True
如果包裹的函数是 Python 生成器函数。
- inspect.isgenerator(object)
- 如果对象是生成器,则返回
True
。
- inspect.iscoroutinefunction(object)
如果对象是 协程函数 (使用 async def 语法定义的函数),则返回
True
。3.5 版中的新功能。
3.8 版更改: 包裹在 functools.partial() 中的函数现在返回
True
,如果包裹的函数是 协程函数 。
- 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 版中的新功能。
3.8 版更改: 包裹在 functools.partial() 中的函数现在返回
True
如果包裹的函数是 异步生成器 函数。
- 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
。数据描述符具有 __set__ 或 __delete__ 方法。 示例是属性(在 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。
- inspect.getsource(object)
返回对象的源代码文本。 参数可以是模块、类、方法、函数、回溯、框架或代码对象。 源代码作为单个字符串返回。 如果无法检索源代码,则会引发 OSError。
- inspect.cleandoc(doc)
清除缩进以与代码块对齐的文档字符串中的缩进。
从第一行中删除所有前导空格。 任何可以从第二行开始统一删除的前导空格都将被删除。 随后删除开头和结尾的空行。 此外,所有选项卡都扩展为空格。
使用 Signature 对象内省可调用对象
3.3 版中的新功能。
Signature 对象表示可调用对象的调用签名及其返回注释。 要检索 Signature 对象,请使用 signature() 函数。
- inspect.signature(callable, *, follow_wrapped=True, globals=None, locals=None, eval_str=False)
为给定的
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() 对象。
对于使用字符串化注释 (
from __future__ import annotations
) 的模块中定义的对象,signature() 将尝试使用 inspect.get_annotations() 自动取消注释的字符串化。global
、locals
、eval_str
参数在解析注解时传入inspect.get_annotations(); 有关如何使用这些参数的说明,请参阅 inspect.get_annotations() 的文档。如果无法提供签名,则引发 ValueError,如果不支持该类型的对象,则引发 TypeError。 此外,如果注释被字符串化,并且
eval_str
不是假的,那么eval()
调用来取消注释的字符串化可能会引发任何类型的异常。函数签名中的斜杠 (/) 表示它之前的参数仅是位置参数。 有关更多信息,请参阅 有关仅位置参数的常见问题解答条目 。
3.5 版新增:
follow_wrapped
参数。 通过False
获得callable
的签名(callable.__wrapped__
将不会用于解包装饰的可调用对象。)3.10 版新增:
globals
、locals
和eval_str
参数。笔记
某些可调用对象在 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, globalns=None, localns=None)
为给定的可调用对象
obj
返回一个 Signature(或其子类)对象。 通过follow_wrapped=False
获得obj
的签名,而无需解开其__wrapped__
链。globalns
和localns
将在解析注释时用作命名空间。此方法简化了 Signature 的子类化:
class MySignature(Signature): pass sig = MySignature.from_callable(min) assert isinstance(sig, MySignature)
3.5 版中的新功能。
3.10 版新增:
globalns
和localns
参数。
- 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
- 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])
基于被替换的实例创建一个新的 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
参数名称到参数值的可变映射。 仅包含明确绑定的参数。 arguments 的变化将反映在 args 和 kwargs 中。
应与 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 版中的新功能。
def test(a, *, b): ... sig = signature(test) ba = sig.bind(10, b=20) test(*ba.args, **ba.kwargs)
类和函数
- inspect.getclasstree(classes, unique=False)
- 将给定的类列表排列成嵌套列表的层次结构。 在嵌套列表出现的地方,它包含从其条目紧接在列表之前的类派生的类。 每个条目都是一个 2 元组,包含一个类和一个其基类的元组。 如果 unique 参数为真,则给定列表中每个类的返回结构中只出现一个条目。 否则,使用多重继承的类及其后代将出现多次。
- inspect.getargspec(func)
获取 Python 函数参数的名称和默认值。 返回一个名为 的元组
ArgSpec(args, varargs, keywords, defaults)
。 args 是参数名称的列表。 varargs 和 keywords 是*
和**
参数或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 是
*
参数的名称,如果不接受任意位置参数,则为None
。 varkw 是**
参数的名称,如果不接受任意关键字参数,则为None
。 defaults 是对应于最后一个 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 是参数名称的列表。 varargs 和 keywords 是*
和**
参数或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)
将 args 和 kwds 绑定到 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 版中的新功能。
- inspect.get_annotations(obj, *, globals=None, locals=None, eval_str=False)
计算对象的注释字典。
obj
可以是可调用的、类或模块。 传入任何其他类型的对象会引发 TypeError。返回一个字典。
get_annotations()
每次调用都会返回一个新的字典; 在同一个对象上调用它两次将返回两个不同但等效的字典。此函数为您处理几个细节:
如果
eval_str
为真,str
类型的值将使用 eval() 取消字符串化。 这旨在与字符串化注释 (from __future__ import annotations
) 一起使用。如果
obj
没有 annotations dict,则返回一个空的 dict。 (函数和方法总是有一个注解字典;类、模块和其他类型的可调用对象可能没有。)忽略类上继承的注释。 如果一个类没有自己的注释字典,则返回一个空字典。
为安全起见,对对象成员和字典值的所有访问都使用
getattr()
和dict.get()
完成。总是,总是,总是返回一个新创建的字典。
eval_str
控制是否将str
类型的值替换为对这些值调用 eval() 的结果:如果 eval_str 为真,则对
str
类型的值调用 eval()。 (请注意,get_annotations
不会捕获异常;如果 eval() 引发异常,它将展开堆栈通过get_annotations
调用。)如果 eval_str 为 false(默认值),则
str
类型的值保持不变。
globals
和locals
传入 eval(); 有关更多信息,请参阅 eval() 的文档。 如果globals
或locals
是None
,则此函数可以用特定于上下文的默认值替换该值,具体取决于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(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_running
和cr_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
- 打印有关指定对象的信息而不是源代码