# 29.12. `inspect` - 检查活动对象

源程序代码︰Lib/inspect.py

`inspect`模块提供了一些有用的函数来帮助获取有关活动对象（如模块，类，方法，函数，跟踪，框架对象和代码对象）的信息。例如，它可以帮助您检查类的内容，检索方法的源代码，提取和格式化函数的参数列表，或获取显示详细追溯所需的所有信息。

这个模块提供了四种主要的服务：类型检查，获取源代码，检查类和函数，以及检查解释器堆栈。

## 29.12.1. 类型和成员

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

类型 | 属性 | 描述
--- | --- | ---
module | __doc__ | 文档字符串
| __file__ | 文件名（内置模块缺失）
class | __doc__ | 文档字符串
| __name__ | 这个类被定义的名称
| __qualname__ | 限定名称
| __module__ | 在这个类中定义的模块的名称
method | __doc__ | 文档字符串
| __name__ | 这个方法被定义的名称
| __qualname__ | 限定名称
| __func__ | 包含方法实现的函数对象
| __self__ | 该方法绑定到的实例，或`None`
function | __doc__ | 文档字符串
| __name__ | 这个函数被定义的名字
| __qualname__ | 限定名称
| __code__ | 包含编译函数bytecode的代码对象
| __defaults__ | 用于位置或关键字参数的任何默认值的元组
| __kwdefaults__ | 为关键字参数映射任何默认值
| __globals__ | 在其中定义了该函数的全局名称空间
| __annotations__ | mapping of parameters names to annotations; `"return"` key is reserved for return annotations.
traceback | tb_frame | 在这个级别的框架对象
| tb_lasti | 字节码中最后一次尝试指令的索引
| tb_lineno | Python源代码中的当前行号
| tb_next | 下一个内部追踪对象（由此级别调用）
frame | f_back | 下一个外框对象（这个框架的调用者）
| f_builtins | 建立了这个框架所看到的名字空间
| f_code | 代码对象在这个框架中被执行
| f_globals | 全局名称空间由此框架看到
| f_lasti | 字节码中最后一次尝试指令的索引
| f_lineno | Python源代码中的当前行号
| f_locals | 本框架所看到的本地名称空间
| f_restricted | 如果帧处于受限执行模式，则为0或1
| f_trace | 追踪此帧的功能，或`None`
code | co_argcount | 参数数量（不包括*或**参数）
| co_code | 原始编译的字节码字符串
| co_consts | 字节码中使用的常量元组
| co_filename | 此代码对象在其中创建的文件的名称
| co_firstlineno | Python源代码中的第一行数
| co_flags | 位图：1 =优化`|` 2 = newlocals `|` 4 = * arg `|` 8 = ** arg
| co_lnotab | 将行号编码为字节码索引
| co_name | 这个代码对象被定义的名称
| co_names | 局部变量名称的元组
| co_nlocals | 局部变量的数量
| co_stacksize | 所需的虚拟机堆栈空间
| co_varnames | 参数名称和局部变量的元组
generator | __name__ | 名称
| __qualname__ | 限定名称
| gi_frame | 帧
| gi_running | 发电机正在运转吗？
| gi_code | 码
| gi_yieldfrom | 对象由`从`产生 ，或`None`
coroutine | __name__ | 名称
| __qualname__ | 限定名称
| cr_await | 对象正在等待，或`None`
| cr_frame | 帧
| cr_running | 协程运行？
| cr_code | 码
builtin | __doc__ | 文档字符串
| __name__ | 此功能或方法的原始名称
| __qualname__ | 限定名称
| __self__ | 绑定方法的实例，或`None`

版本3.5中的更改：将`__qualname__`和`gi_yieldfrom`属性添加到生成器。

现在生成器的`__ name __`属性是根据函数名称中设置的，而不是代码名称，并且可以修改。

`inspect.``getmembers`(object[, predicate])

  返回按名称排序的（name, value)列表中的所有成员对象。如果提供了可选的predicate参数，则只包含predicate返回true值的成员。

  注意

  当参数是一个类时，`getmembers()`只会返回已定义在元类中的类属性，并且这些属性已经列在元类的自定义`__ dir __()`中。

`inspect.``getmoduleinfo`(path)

  返回一个命名元组 `ModuleInfo（name， suffix， mode， module_type）`描述Python如何解释由path标识的文件是模块，或者返回`None`，如果没被标识为模块。In that tuple, name is the name of the module without the name of any enclosing package, suffix is the trailing part of the file name (which may not be a dot-delimited extension), mode is the `open()` mode that would be used (`'r'` or `'rb'`), and module_type is an integer giving the type of the module. module_type将具有可与`imp`模块中定义的常量进行比较的值；有关模块类型的更多信息，请参阅该模块的文档。

  从版本3.3开始弃用：您可以根据`importlib.machinery`中列出的受支持后缀检查文件路径的后缀，以推断相同的信息。

`inspect.``getmodulename`(path)

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

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

  版本3.3中更改：此函数现在直接基于`importlib`，而不是已弃用的`getmoduleinfo()`。

`inspect.``ismodule`(object)

  如果对象是模块，则返回true。

`inspect.``isclass`(object)

  如果对象是一个类，无论是内置的还是用Python代码创建的，则返回true。

`inspect.``ismethod`(object)

  如果对象是用Python编写的绑定方法，则返回true。

`inspect.``isfunction`(object)

  如果对象是一个Python函数（包含由lambda表达式创建的函数），则返回true。

`inspect.``isgeneratorfunction`(object)

  如果对象是Python生成器函数，则返回true。

`inspect.``isgenerator`(object)

  如果对象是一个生成器，则返回true。

`inspect.``iscoroutinefunction`(object)

  如果对象是coroutine function（用`async def`语法定义的函数），则返回true。

  版本3.5中的新功能。

`inspect.``iscoroutine`(object)

  如果对象是由`async def`函数创建的coroutine，则返回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.``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，但如果`ismethod()`，`isclass()`，`isfunction()`或`isbuiltin()`是真的。

  例如，这对于`int.__add__`是真的。通过此测试的对象有一个`__get__()`方法，但不包含`__set__()`方法，但除此之外，该组属性会发生变化。一个`__name__`属性通常是合理的，常常是`__doc__`。

  Methods implemented via descriptors that also pass one of the other tests return false from the `ismethoddescriptor()` test, simply because the other tests promise more – you can, e.g., count on having the `__func__` attribute (etc) when an object passes `ismethod()`.

`inspect.``isdatadescriptor`(object)

  如果对象是数据描述符，则返回true。

  数据描述符有一个`__get__`和一个`__set__`方法。示例是属性（在Python中定义），getset和成员。后两种是在C中定义的，并且这些类型有更多特定的测试可用，这在Python实现中是健壮的。通常情况下，数据描述符也将具有`__name__`和`__doc__`属性（属性，getset和成员都具有这两个属性），但不能保证。

`inspect.``isgetsetdescriptor`(object)

  如果对象是getset描述符，则返回true。

  CPython implementation detail: getsets are attributes defined in extension modules via `PyGetSetDef` structures. 对于没有这种类型的Python实现，此方法将始终返回`False`。

`inspect.``ismemberdescriptor`(object)

  如果对象是成员描述符，则返回true。

  CPython implementation detail: Member descriptors are attributes defined in extension modules via `PyMemberDef` structures. 对于没有这种类型的Python实现，此方法将始终返回`False`。

## 29.12.2. 检索源代码

`inspect.``getdoc`(object)

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

  版本3.5中已更改：文档字符串现在如果未被覆盖，现在将被继承。

`inspect.``getcomments`(object)

  在单个字符串中返回紧接在对象源代码之前（对于类，函数或方法）或Python源文件顶部（如果对象是模块）的任何注释行。

`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)

  清除缩排以排列代码块的文档字符串中的缩进。

  从第一行删除所有主要的空白字符。任何可从第二行向前均匀删除的空白字符将被删除。随后删除开头和结尾的空行。此外，所有选项卡都扩展为空格。

## 29.12.3. 使用Signature对象抽象可调式对象

版本3.3中的新功能。

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

  从普通函数和类到`functools.partial()`对象接受大量的python可调参数。

  如果不提供签名，则引发`ValueError`；如果不支持该类型的对象，则引发`TypeError`。

  版本3.5中的新功能： `follow_wrapped`参数。通过`False`获得`callable`的特征（`callable.__wrapped__`不会用于解开装饰可调用）。

  注意

  在Python的某些实现中，某些可调用对象可能不是内省的。例如，在CPython中，C中定义的一些内置函数不提供关于它们参数的元数据。

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

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

  可选的参数参数是一系列`Parameter`对象，经过验证可以检查是否没有带重复名称的参数，并且参数的顺序是正确的首先是位置，然后是位置或关键字，并且具有默认值的参数遵循没有默认值的参数。

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

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

  在版本3.5中更改：签名对象是可挑选和可散列的。

  `empty`

    一种特殊的级别标记，用于指定缺少返回注释。

  `parameters`

    参数名称到相应的`Parameter`对象的有序映射。

  `return_annotation`

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

  `bind`(*args, **kwargs)

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

  `bind_partial`(*args, **kwargs)

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

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

    根据调用的实例替换创建新的Signature实例。可以传递不同的`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`（或其子类）对象。Pass `follow_wrapped=False` to get a signature of `obj` without unwrapping its `__wrapped__` chain.

    该方法简化了`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])

    > Create a new Parameter instance based on the instance replaced was invoked on. To override a `Parameter` attribute, pass the corresponding argument. To remove a default value or/and an annotation from a Parameter, pass `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'"

    Changed in version 3.4: In Python 3.3 Parameter objects were allowed to have `name` set to `None` if their `kind` was set to `POSITIONAL_ONLY`. 这不再被允许。

class `inspect.``BoundArguments`

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

  `arguments`

    参数'名称到参数'值的有序可变映射（`collections.OrderedDict`）。仅包含显式绑定的参数。`arguments`将反映在`args`和`kwargs`中。

    应该与`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中的新功能。

  `args`和`kwargs`属性可用于调用函数：

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

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

也可以看看

PEP 362 - 功能签名对象。
  详细的规范，实现细节和示例。

## 29.12.4. 类和函数

`inspect.``getclasstree`(classes, unique=False)

  将给定的类列表排列成嵌套列表的层次结构。在出现嵌套列表的情况下，它包含从其条目紧接在列表之前的类派生的类。每个条目都是一个2元组，其中包含一个类和其基类的元组。如果唯一参数为true，则给定列表中每个类的返回结构中只会出现一个条目。否则，使用多重继承的类和它们的后代将多次出现。

`inspect.``getargspec`(func)

  获取Python函数参数的名称和默认值。named tuple `ArgSpec（args， varargs， 关键字， 默认值） t6 >`返回。args是参数名称的列表。varargs和关键字是`*`和`**`参数的名称或`None` 。默认值是默认参数值的元组，或`None`，如果没有默认参数的话；如果这个元组具有n元素，则它们对应于args中列出的最后一个n元素。

  从版本3.0开始弃用：使用`signature()`和Signature Object，为可调参数提供更好的内省API。

`inspect.``getfullargspec`(func)

  获取Python函数参数的名称和默认值。A named tuple is returned:

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

  args是参数名称的列表。varargs和varkw是`*`和`**`参数的名称或`None` 。默认值是最后一个n参数的默认值的n值，或`None`默认参数。kwonlyargs是关键字参数名称列表。kwonlydefaults是将kwonlyargs中的名称映射为默认值的字典。注释是将参数名称映射到注释的字典。

  元组中的前四项对应于`getargspec()`。

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

  从版本3.5开始不推荐使用：使用`signature()`和Signature Object，为可调参数提供更好的内省API。

`inspect.``getargvalues`(frame)

  获取有关传递到特定框架的参数的信息。A named tuple `ArgInfo(args, varargs, keywords, locals)` is returned. args是参数名称的列表。varargs和关键字是`*`和`**`参数的名称或`None` 。locals is the locals dictionary of the given frame.

  从版本3.5开始不推荐使用：使用`signature()`和Signature Object，为可调参数提供更好的内省API。

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

  根据`getargspec()`或`getfullargspec()`返回的值格式化漂亮的参数规范。

  前七个参数是（`args`，`varargs`，`varkw`，`defaults`，`kwonlyargs` ，`kwonlydefaults`，`annotations`）。

  The other six arguments are functions that are called to turn argument names, `*` argument name, `**` argument name, default values, return annotation and individual annotations into strings, respectively.

  例如：

      >>> 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()`返回的四个值格式化漂亮的参数规范。格式*参数是相应的可选格式函数，被称为将名称和值转换为字符串。

  从版本3.5开始不推荐使用：使用`signature()`和Signature Object，为可调参数提供更好的内省API。

`inspect.``getmro`(cls)

  以方法解析顺序返回cls基类的元组，包括cls。这个元组中不会出现多次类。请注意，方法解析顺序取决于cls的类型。除非使用非常独特的用户定义的元类型，否则cls将是元组的第一个元素。

`inspect.``getcallargs`(func, *args, **kwds)

  将args和kwds绑定到Python函数或方法func的参数名称，就好像它们是用它们调用的一样。对于绑定方法，还要将第一个参数（通常名为`self`）绑定到关联的实例。返回一个字典，将参数名称（包括`*`和`**`参数的名称，如果有的话）映射到args和kwds。在错误地调用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中的外部名称引用到其当前值的映射。named tuple `ClosureVars（nonlocals， 全局变量， 内置变量， 未绑定） t6 >`返回。nonlocals将引用名称映射到词法封闭变量，将globals映射到函数的模块全局变量，将builtins映射到可从函数体可见的内建变量。unbound是函数中引用的名称集，根据当前的模块全局变量和内建函数，它们根本无法解析。

  `TypeError` is raised if func is not a Python function or method.

  版本3.3中的新功能。

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

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

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

  `ValueError` is raised if a cycle is encountered.

  版本3.4中的新功能。

## 29.12.5. 解释器堆栈

When the following functions return “frame records,” each record is a named tuple `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)

  获取关于帧或追溯对象的信息。A named tuple `Traceback(filename, lineno, function, code_context, index)` is returned.

`inspect.``getouterframes`(frame, context=1)

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

  Changed in version 3.5: A list of named tuples `FrameInfo(frame, filename, lineno, function, code_context, index)` is returned.

`inspect.``getinnerframes`(traceback, context=1)

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

  Changed in version 3.5: A list of named tuples `FrameInfo(frame, filename, lineno, function, code_context, index)` is returned.

`inspect.``currentframe`()

  返回当前调用者的堆栈框架的框架对象。

  CPython implementation detail: This function relies on Python stack frame support in the interpreter, which isn’t guaranteed to exist in all implementations of Python. 如果在没有Python堆栈帧支持的实现中运行，该函数返回`None`。

`inspect.``stack`(context=1)

  返回调用者堆栈的帧记录列表。返回列表中的第一个条目表示调用者；最后一个条目代表堆叠上最外面的呼叫。

  Changed in version 3.5: A list of named tuples `FrameInfo(frame, filename, lineno, function, code_context, index)` is returned.

`inspect.``trace`(context=1)

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

  Changed in version 3.5: A list of named tuples `FrameInfo(frame, filename, lineno, function, code_context, index)` is returned.

## 29.12.6. 静态获取属性

当获取或检查属性的存在时，`getattr()`和`hasattr()`都可以触发代码执行。描述符（如属性）将被调用，并且可以调用`__getattr__()`和`__getattribute__()`。

对于需要被动内省的情况，如文档工具，这可能不方便。`getattr_static()` has the same signature as `getattr()` but avoids executing code when it fetches attributes.

`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

## 29.12.7. 发生器和协程的当前状态

在实现协程调度程序和生成器的其他高级用途时，确定生成器当前是否正在执行，是否正在等待启动或恢复或执行或已经终止会很有用。`getgeneratorstate()` allows the current state of a generator to be determined easily.

`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，并且没有当前关联的帧，则返回空字典。`TypeError` is raised if generator is not a Python generator object.

  CPython implementation detail: This function relies on the generator exposing a Python stack frame for introspection, which isn’t guaranteed to be the case in all implementations of Python. 在这种情况下，该函数将始终返回一个空字典。

  版本3.3中的新功能。

`inspect.``getcoroutinelocals`(coroutine)

  这个函数类似于`getgeneratorlocals()`，但是对由`async def`函数创建的协程对象起作用。

  版本3.5中的新功能。

## 29.12.8. 命令行界面

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

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

`--details```

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