CPython inspect 模块完全指南:运行时内省、签名解析与解释器栈探测
inspect 是 CPython 标准库中面向"活对象"(live objects)的元编程核心工具。它围绕模块、类、方法、函数、traceback、帧(frame)与代码对象(code object)提供四类服务:类型与成员检查、源码获取、可调用对象签名解析、以及解释器调用栈探测。读完本文,你将掌握用 inspect 构建调试器、参数校验层、自动化文档生成器与协程调度器等工具所需的全部 API、底层对象模型与源码实现路径。
本文以 CPython 官方库参考 Doc/library/inspect.rst 为骨架,结合纯 Python 实现 Lib/inspect.py(当前版本约 3500 行)与测试套件 Lib/test/test_inspect/ 展开,逐项说明函数语义、可作用对象、异常约定与版本演化。
一、模块概览:四种服务与使用入口
模块入口文档(Doc/library/inspect.rst)将该模块能力划分为四类:
- 类型检查(type checking):对对象属于模块、类、方法、函数等哪种类型给出布尔判定;
- 获取源码(getting source code):取回某对象的源文件、源行、注释与整理后的 docstring;
- 检查类与函数(inspecting classes and functions):解析参数列表、方法解析顺序(MRO)、闭包变量等;
- 检查解释器栈(examining the interpreter stack):遍历帧对象与 traceback,还原调用现场。
inspect 的模块级 docstring(Lib/inspect.py 顶部)自述其设计目标:"封装内部特殊属性(co_、tb_* 等)为更友好的接口"*。也就是说,inspect 本质上是把散落在各对象上的双下划线/单下划线属性(__doc__、__code__、f_back、tb_next……)包装成一组语义化函数。
使用 getmembers 获取对象全部成员、用 is* 系列函数作为筛选谓词,是该模块最经典的使用范式。测试目录 Lib/test/test_inspect/ 中的 inspect_fodder.py、inspect_fodder2.py 等"喂料"模块定义了大量用于验证的类层级,是理解各 API 边界的最佳活例。
二、类型与成员:getmembers 与 is* 谓词
2.1 成员枚举
getmembers(object[, predicate]):返回对象所有成员,形如(name, value)的列表并按名字排序。可选谓词以每个成员的value为参数调用,只保留返回真值的成员。注意:当参数是类时,只有被元类自定义__dir__列出的元类属性才会被返回。getmembers_static(object[, predicate])(3.11+):与getmembers类似,但不触发描述符协议、__getattr__与__getattribute__的动态查找。它可能取不到getmembers能取到的动态属性(如实例运行时新加属性),也可能"发现"getmembers取不到的东西(如会抛AttributeError的描述符),某些场景下返回描述符对象而非实例成员。
从实现看(Lib/inspect.py),二者共享私有函数 _getmembers(object, predicate, getattr),差别仅在第三个参数分别传入 getattr 与 getattr_static——一个函数就说明了"静态成员遍历"的本质:只是换掉取值函数。
2.2 各类型对象的特殊属性总表
getmembers 的返回值能覆盖哪些"期望属性",取决于对象类型。下表整理自官方文档(原表见 Doc/library/inspect.rst),模块属性另见 importlib 相关文档:
| 类型 | 属性 | 说明 |
|---|---|---|
| class | __doc__ |
文档字符串 |
__name__ |
定义时使用的类名 | |
__qualname__ |
限定名(含所在类/模块路径) | |
__module__ |
定义所在模块名 | |
__type_params__ |
泛型类的类型参数元组(PEP 695) | |
| method(绑定方法) | __doc__ / __name__ / __qualname__ / __module__ |
同上语义 |
__func__ |
承载方法实现的函数对象 | |
__self__ |
方法绑定到的实例,未绑定时为 None |
|
| function | __doc__ / __name__ / __qualname__ / __module__ |
同上语义 |
__code__ |
含编译后字节码的代码对象 | |
__defaults__ |
位置/关键字参数的默认值元组 | |
__kwdefaults__ |
仅限关键字参数默认值的映射 | |
__globals__ |
定义该函数的全局命名空间 | |
__builtins__ |
builtins 命名空间(3.10+) | |
__annotations__ |
参数名到注解的映射,"return" 键保留给返回注解 |
|
__type_params__ |
泛型函数的类型参数元组 | |
| traceback | tb_frame / tb_lasti / tb_lineno / tb_next |
本层帧对象、最后尝试指令的字节码下标、当前源码行号、被本层调用的内层 traceback |
| frame | f_back |
外层帧(调用者) |
f_builtins / f_globals / f_locals |
本帧可见的 builtins / 全局 / 局部命名空间 | |
f_code |
本帧正在执行的代码对象 | |
f_lasti / f_lineno |
最后尝试指令下标 / 当前源码行号 | |
f_generator |
拥有该帧的生成器或协程对象;普通函数帧为 None(3.14+) |
|
f_trace / f_trace_lines / f_trace_opcodes |
本帧跟踪函数及是否逐行/逐操作码触发跟踪事件 | |
clear() |
清除对局部变量的全部引用 | |
| code | co_argcount / co_posonlyargcount / co_kwonlyargcount |
参数个数(不含 keyword-only、*、**)等细分计数 |
co_code |
原始编译字节码字符串 | |
co_cellvars / co_freevars |
单元变量(被外层作用域引用)与自由变量(经闭包引用) | |
co_consts / co_names / co_varnames / co_nlocals / co_stacksize |
常量、非局部名字、局部变量、栈空间等元数据 | |
co_filename / co_firstlineno / co_name / co_qualname |
文件名、首行号、名字、限定名 | |
co_flags |
CO_* 标志位图(见后文专节) |
|
co_lines() / co_positions() |
产出字节码区间 / 每个指令源码位置 | |
replace() |
返回替换字段后的代码对象副本 | |
| generator | __name__ / __qualname__ |
名字与限定名 |
gi_frame / gi_code |
帧与代码对象 | |
gi_running / gi_suspended |
是否运行中 / 是否挂起于 yield(后者 3.11+) | |
gi_yieldfrom |
yield from 迭代的对象,无则为 None |
|
gi_state |
状态之一(3.15+,详见状态节) | |
| async generator | ag_await / ag_frame / ag_code |
被 await 对象(可为 None)、帧、代码 |
ag_running / ag_suspended |
运行/挂起标志 | |
ag_state |
AGEN_* 状态(3.15+) |
|
| coroutine | cr_await / cr_frame / cr_code |
被 await 对象、帧、代码 |
cr_running / cr_suspended |
运行/挂起标志 | |
cr_origin |
协程创建点(配合 sys.set_coroutine_origin_tracking_depth,3.7+) |
|
cr_state |
CORO_* 状态(3.15+) |
|
| builtin | __doc__ / __name__ / __qualname__ / __self__ |
内置函数/方法的文档、原名、限定名、绑定实例 |
关键版本变更:3.5 起生成器 __name__ 取自函数名且可修改,新增 gi_yieldfrom;3.7 新增 cr_origin;3.10 函数新增 __builtins__;3.11/3.12 分别为生成器与协程增加 gi_suspended/cr_suspended,异步生成器则于 3.12 增加 ag_suspended;3.14 帧增加 f_generator;3.15 为三类协程对象统一增加 *_state。
2.3 is* 谓词系列
这些谓词最主要的用途正是充当 getmembers 的第二参数:
ismodule、isclass、ispackage(3.14+):模块 / 类(内置类与 Python 类均可,对泛型别名如list[int]返回False)/ 包判断;ismethod:Python 编写的绑定方法。文档用Greeter示例区分绑定方法与普通函数——通过实例访问返回绑定方法(ismethod(...) is True、isfunction(...) is False),通过类访问返回函数本身(结论相反);isfunction:Python 函数,含lambda;isgeneratorfunction、isgenerator:生成器函数 / 生成器对象。对生成器函数派生的绑定方法同样返回真;3.8 起支持functools.partial包裹,3.13 起支持functools.partialmethod包裹;iscoroutinefunction:以async def定义的协程函数,也接受partial包裹、partialmethod包裹(3.13+)及被markcoroutinefunction标记的同步函数(3.12+)。注意该函数不保证对"返回协程的同步函数"返回真,这正是引入标记机制的原因;markcoroutinefunction(func)(3.12+):装饰器,为无法被自动识别的"返回协程的同步函数"打标。官方建议优先用async def;其次可调用后以iscoroutine验证返回值;iscoroutine:async def函数创建的协程对象;isawaitable:可用于await表达式的对象,能区分基于生成器的协程与普通生成器——配合types.coroutine装饰器的示例:普通gen()不可 await,gen_coro()可 await;isasyncgenfunction、isasyncgen:异步生成器函数与迭代器(3.6+),同样兼容 partial/partialmethod 包裹;istraceback、isframe、iscode:traceback / 帧 / 代码对象;isbuiltin:内置函数或绑定的内置方法;ismethodwrapper(3.11+):types.MethodWrapperType实例,如__str__、__eq__、__repr__;isroutine:用户定义或内置的函数/方法;isabstract:抽象基类(ABC);ismethoddescriptor:方法描述符(对同时满足isclass/ismethod/isfunction的对象返回False)。例如int.__add__即通过该测试——有__get__而无__set__/__delete__。3.13 修正了一处误判:仅有__get__+__delete__而无__set__的对象属于数据描述符而非方法描述符;isdatadescriptor:数据描述符(恒具__set__或__delete__),典型如property、getset 与 member 描述符。3.8 放宽为"只要有__set__即算";isgetsetdescriptor、ismemberdescriptor:分别对应扩展模块中以PyGetSetDef、PyMemberDef结构定义的属性(见 CPython C-API),无此类类型的 Python 实现恒为False。
分类辅助还有 classify_class_attrs(cls),返回 Attribute(name, kind, defining_class, object) 四元组,把成员分成 'class method'、'static method'、'property'、'method'、'data' 等类别(实现在 Lib/inspect.py)。
2.4 其它常用辅助
getmodulename(path):由文件路径猜模块名(剥去扩展名)。扩展名必须命中importlib.machinery.all_suffixes()才返回名字,否则返回None;对包目录路径同样返回None。3.3 起直接基于 importlib 实现。
三、获取源码:getsource 家族与文档字符串整理
getdoc(object, *, inherit_class_doc=True, fallback_to_class_doc=True, dedent=True):返回经cleandoc整理的文档字符串。对象无 docstring 时按序回退:类是且inherit_class_doc为真 → 沿继承层级取;方法/property/描述符 → 沿继承层级取;否则若fallback_to_class_doc为真 → 取对象的类。无效或缺失返回None。3.5 起 docstring 可被继承;3.15 起新增两个开关参数并支持functools.cached_property上的 docstring 继承;dedent为新增参数(见下文);cleandoc(doc, *, dedent=True):清洗缩进的 docstring。规则:首行去除全部前导空白;后续各行统一去除可均匀去掉的缩进(dedent=False时跳过);剥除首尾空行;制表符展开为空格。由于 Python 3.13 起编译器会自行去掉 docstring 缩进,dedent实际只影响非源码 docstring(如 Argument Clinic 生成、缩进有意义的文本);getcomments(object):返回紧邻对象源码之前(类/函数/方法)或源文件顶部(模块)的注释,多行合并为一个字符串;对象无源码(C 扩展或交互式 shell 定义)返回None;getfile(object):对象定义所在(文本或二进制)文件名。取不到源码抛OSError;对内置模块/类/函数抛TypeError;getsourcefile(object):Python 源文件名;无法定位返回None;取不到源码抛OSError,内置对象抛TypeError;getmodule(object):猜测对象所在模块,失败返回None;getsource(object)与getsourcelines(object):前者把对象源码作为单个字符串返回,后者返回(行列表, 起始行号)。二者可接受模块、类、方法、函数、traceback、帧、代码对象;C 内置对象抛TypeError(3.3 起 IOError 被并入 OSError)。
四、可调用对象签名:Signature / Parameter / BoundArguments
Signature 体系(PEP 362 的实现)自 3.3 引入,是 inspect 中工程价值最高、被第三方框架引用最多的部分。
4.1 获取签名:signature()
signature(callable, *, follow_wrapped=True, globals=None, locals=None, eval_str=False, annotation_format=Format.VALUE) 返回 Signature 对象,接受从普通函数、类到 functools.partial 的广泛可调用对象。文档示例:
>>> 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'>
要点:
- 自动反字符串化注解:若注解是字符串(如使用了
from __future__ import annotations),signature会借助annotationlib.get_annotations尝试求值还原,globals/locals/eval_str透传给该函数;annotation_format(3.14+)可传annotationlib.Format.STRING等以控制返回注解形态; - 错误约定:无法提供签名抛
ValueError;不支持的对象类型抛TypeError;字符串化注解且eval_str非假时,反序列化eval()可能抛出任意异常; - 斜杠语义:签名中的
/表示其前参数为 positional-only(详见 FAQ 关于仅限位置参数的说明,涉及 CPython 3.8+ 的/语法); follow_wrapped(3.5+)默认跟踪__wrapped__链解开装饰器;传False只看对象自身;- 兼容性边界:部分 C 实现的 builtin 不提供参数元数据,无法被内省(如某些 CPython 内置函数);
- 实现细节:若对象定义了
__signature__属性,可能以其构建签名——确切语义属实现细节。从源码看,顶层signature()直接委托Signature.from_callable(...)(Lib/inspect.py),真正的逻辑分布在_signature_from_function(Lib/inspect.py)与_signature_from_callable(Lib/inspect.py)两个私有函数中,后者负责 unwrap、查询__signature__、区分内置函数与各类对象的分派。
4.2 Signature 类
Signature(parameters=None, *, return_annotation=Signature.empty) 表示函数签名及返回注解。构造时会校验:无重名参数、顺序合法(positional-only 在前,带默认值参数排在无默认值之后)。Signature 对象不可变,修改副本用 replace 或 copy.replace;3.5 起可 pickle、可哈希。源码用 __slots__ = ('_return_annotation', '_parameters') 保证不可变与紧凑(Lib/inspect.py)。
Signature.empty:类级哨兵,表示无返回注解;Signature.parameters:参数名到Parameter的有序映射,含 keyword-only 参数,严格按定义顺序排列(3.7 起语言层显式保证 keyword-only 顺序);Signature.return_annotation:返回注解,无则empty;Signature.bind(*args, **kwargs):把实参映射到形参,匹配成功返回BoundArguments,否则抛TypeError;Signature.bind_partial(*args, **kwargs):同bind但允许缺省必填参数(模拟functools.partial);Signature.replace(*[, parameters][, return_annotation]):基于原对象构造新签名,覆盖指定字段;用empty移除返回注解。文档示例用sig.replace(return_annotation="new return anno")得到"(a, b) -> 'new return anno'";Signature.format(*, max_width=None, quote_annotation_strings=True)(3.13+):字符串化。传max_width时尽量折行,超过则每个参数独占一行;quote_annotation_strings=False可去掉字符串注解的引号(适配Format.STRING或 future annotations 场景)。3.14 起增加unquote_annotations兼容参数;Signature.from_callable(obj, ...)(类方法,3.5+):与signature()行为一致但允许子类化Signature(示例MySignature.from_callable(sum)返回MySignature实例),3.10 起同样接受 globals/locals/eval_str。
4.3 Parameter 类
Parameter(name, kind, *, default=Parameter.empty, annotation=Parameter.empty) 不可变(修改用 replace/copy.replace),3.5 起可 pickle、可哈希。
Parameter.empty:哨兵,表示无默认值/无注解;Parameter.name:参数名字符串,必须是合法 Python 标识符。实现细节:CPython 为推导式/生成器表达式的代码对象生成形如.0的隐式参数名,3.6 起本模块以implicit0之类名字暴露;Parameter.default/Parameter.annotation:默认值 / 注解,无则empty;Parameter.kind:参数绑定方式枚举,按序支持比较:
| kind 取值 | 含义 |
|---|---|
POSITIONAL_ONLY |
必须以位置实参提供(定义中 / 之前的参数) |
POSITIONAL_OR_KEYWORD |
位置或关键字均可(Python 函数默认行为) |
VAR_POSITIONAL |
未绑定到其它形参的位置实参元组,即 *args |
KEYWORD_ONLY |
必须以关键字提供(* 或 *args 之后) |
VAR_KEYWORD |
未绑定的关键字实参字典,即 **kwargs |
Parameter.kind.description(3.8+)返回可读描述,示例输出 positional or keyword、keyword-only 等。文档中的过滤示例是经典写法:遍历 sig.parameters.values(),命中 kind == KEYWORD_ONLY and default is empty 即打印无默认值的仅关键字参数。Parameter.replace 支持按需覆盖 name/kind/default/annotation,用 empty 移除默认值或注解。
4.4 BoundArguments 类
Signature.bind/bind_partial 的返回结果,承载"实参→形参"映射:
arguments:参数名到实参值的可变映射,只含显式绑定项(依赖默认值的参数被跳过),改动会同步反映到args/kwargs。3.9 起类型为dict(此前为OrderedDict);args:位置实参值元组,由arguments动态计算;kwargs:关键字实参字典,凡可位置传递的实参都进args而非kwargs;signature:父Signature引用;apply_defaults()(3.5+):补上缺失参数的默认值——*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': ()}
args/kwargs 可直接解包调用目标函数:
def test(a, *, b):
...
sig = signature(test)
ba = sig.bind(10, b=20)
test(*ba.args, **ba.kwargs)
getfullargspec 在文档中明示:"signature 与 Signature Object 是推荐的可调用对象内省 API,本函数主要为兼容 Python 2 inspect 模块 API 保留"(详见下文)。
五、类与函数内省辅助
getclasstree(classes, unique=False):把类列表排成嵌套层级。嵌套列表表示其前一个类的派生类;每个条目是(类, 基类元组)二元组。unique=True时每个类只出现一次,否则多重继承的类及其后代可重复出现;getmro(cls):返回含cls在内的基类元组,按方法解析顺序排列且不重复(cls通常为第一项,除非使用特殊元类);getfullargspec(func, *, annotation_format=Format.VALUE):返回具名元组FullArgSpec(args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations)。其中defaults是末尾n个位置参数的默认值元组,无默认值时是None;annotations字典的"return"键保留给返回注解。历史沿革:3.4 起基于signature实现,但忽略__wrapped__、对绑定方法会包含已绑定的首参;3.5 曾被标记弃用,3.6 撤销弃用以支持单源 Python 2/3 代码迁移;3.15 新增annotation_format。警告:默认VALUE格式下构造某些 argspec 可能抛异常;getargvalues(frame):返回ArgInfo(args, varargs, keywords, locals)。其中args为参数名列表,varargs/keywords为*/**参数名或None,locals为该帧的局部字典。配套的formatargvalues(...)把四个值格式化为漂亮的参数说明(format*形参是可选的自定义格式化回调)。二者都曾在 3.5 被误标弃用(文档特别澄清);getcallargs(func, /, *args, **kwds):把实参绑定到形参名,如同真正调用(含self绑定),返回名字→值字典;调用不合法时抛出与func(*args, **kwds)相同类型与相近信息的异常。3.5 起弃用,改用Signature.bind/bind_partial;getclosurevars(func):返回ClosureVars(nonlocals, globals, builtins, unbound)。nonlocals映射词法闭包变量,globals映射模块全局,builtins映射函数体内可见的内置名,unbound是当前模块全局与内置下都无法解析的名字集合。对非 Python 函数/方法抛TypeError(3.3+);unwrap(func, *, stop=None)(3.4+):沿__wrapped__链取最内层对象。stop是接收链上对象、返回真即提前终止的回调——signature内部正是用它来在遇到带__signature__的对象时停止解包;遇环抛ValueError;get_annotations(obj, *, globals=None, locals=None, eval_str=False, format=annotationlib.Format.VALUE):3.10 引入,3.14 起成为annotationlib.get_annotations的别名(旧调用方式仍可用)。安全警告:该函数可能执行注解中蕴含的任意代码,相关风险详见 annotationlib 文档的安全专节。
六、解释器栈探测
本节函数围绕 frame 对象构建调用栈视图,返回的 FrameInfo 记录对象。
6.1 记录类型
FrameInfo:字段frame(帧对象)、filename、lineno(当前执行行号)、function(执行中的函数名)、code_context(源码上下文行列表)、index(当前行在code_context中的下标)、positions(dis.Positions,含起始/结束行列)。3.5 为具名元组;3.11 改为类实例但向后兼容元组式操作;Traceback(getframeinfo的返回类型,3.11 起):字段与 FrameInfo 相同的 traceback 视角记录(filename/lineno/function/code_context/index/positions)。
引用循环警告:保留帧对象会造成引用环,使可达对象生命周期显著拉长(即便启用循环 GC)。建议用 finally: del frame 确定性释放,或调用 frame.clear() 打破循环:
def handle_stackframe_without_leak():
frame = inspect.currentframe()
try:
# do something with the frame
finally:
del frame
各函数普遍支持可选的 context 参数,指定以当前行为中心返回的上下文行数。
6.2 栈与帧 API
getframeinfo(frame, context=1):取帧或 traceback 的信息,返回Traceback对象(3.11 前为具名元组);getouterframes(frame, context=1):返回frame及其全部外层帧的FrameInfo列表——代表产生 frame 的调用链,首项即 frame 本身,末项为最外层调用;getinnerframes(traceback, context=1):返回 traceback 帧及其内层帧列表——代表 frame 引发的后续调用,首项为 traceback,末项为异常抛出点;currentframe():返回调用者的栈帧。实现细节:依赖解释器的 Python 栈帧支持,无帧支持的实现返回None;stack(context=1):调用者调用栈的FrameInfo列表,首项是调用者,末项是最外层;trace(context=1):当前帧到正在处理异常抛出帧之间栈的FrameInfo列表。
这些函数在 Lib/inspect.py 中围绕帧遍历实现,getframeinfo 从第 1602 行起、currentframe 从第 1688 行起,均有对应单元测试覆盖(见 Lib/test/test_inspect/)。
七、静态属性获取:getattr_static
getattr/hasattr 在取属性时会执行代码:property 等描述符被调用,__getattr__/__getattribute__ 可能触发。文档工具这类"被动内省"场景需要 getattr_static(obj, attr[, default])(3.2+)——签名类似 getattr,但取属性时不触发描述符协议、__getattr__、__getattribute__。
局限性(文档明示):可能取不到动态创建属性、可能取到 getattr 取不到的(如抛 AttributeError 的描述符);__dict__ 被同名成员(如 property)遮蔽时无法找到实例成员。
getattr_static 不解析 slot 描述符与 C 实现的 getset 描述符,返回的是描述符对象本身。文档给出解析内置描述符类型的模板:
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:
pass # 描述符可能以 AttributeError 表示无底层值
注意:对任意 getset 描述符调用 __get__ 可能触发代码执行。实现上,getmembers_static 正复用了 getattr_static(见 Lib/inspect.py)。
八、生成器、协程与异步生成器状态查询
实现协程调度器等高级用法时,需要判断生成器处于"待执行、运行中、挂起还是已终止"。状态常量定义于 Lib/inspect.py:
getgeneratorstate(generator)(3.2+):状态为GEN_CREATED(等待开始)、GEN_RUNNING(解释器正在执行)、GEN_SUSPENDED(挂起于 yield 表达式)、GEN_CLOSED(执行完毕);getcoroutinestate(coroutine)(3.5+):CORO_CREATED/CORO_RUNNING/CORO_SUSPENDED(挂起于 await)/CORO_CLOSED。本为async def协程设计,但接受任何具cr_running/cr_frame属性的协程样对象;getasyncgenstate(agen)(3.12+):AGEN_CREATED/AGEN_RUNNING/AGEN_SUSPENDED/AGEN_CLOSED,接受具ag_running/ag_frame的异步生成器样对象。
还有查询内部活局部变量的函数,多用于测试以确保内部状态更新符合预期:
getgeneratorlocals(generator)(3.3+):生成器活局部变量名→值映射,等价于在生成器体内调用locals()(含同样注意点)。无关联帧时返回空字典;非 Python 生成器抛TypeError。实现依赖生成器暴露可内省的 Python 栈帧,不支持时恒返回空字典;getcoroutinelocals(coroutine)(3.5+)、getasyncgenlocals(agen)(3.12+):同前者,分别面向协程与异步生成器。
九、代码对象的 CO_* 位标志
code.co_flags 是位图。各标志语义(均为 CPython 特有,其它实现可能缺失,且属于实现细节、未来可能变动——官方强烈建议优先使用 inspect 的公开 API):
| 标志 | 含义 |
|---|---|
CO_OPTIMIZED |
代码已优化,使用快速局部变量 |
CO_NEWLOCALS |
置位时执行该代码会为帧 f_locals 新建字典 |
CO_VARARGS |
有 *args 样可变位置参数 |
CO_VARKEYWORDS |
有 **kwargs 样可变关键字参数 |
CO_NESTED |
代码对象为嵌套函数 |
CO_GENERATOR |
生成器函数,执行返回生成器对象 |
CO_COROUTINE |
协程函数,执行返回协程对象(PEP 492,3.5+) |
CO_ITERABLE_COROUTINE |
把生成器转为基于生成器的协程,可 await 且可 yield from 协程(PEP 492,3.5+) |
CO_ASYNC_GENERATOR |
异步生成器函数,执行返回异步生成器对象(PEP 525,3.6+) |
CO_HAS_DOCSTRING |
源码带 docstring,且其为 co_consts 首项(3.14+) |
CO_METHOD |
在类作用域内定义的函数(3.14+) |
十、缓冲区标志 BufferFlags
BufferFlags 是 enum.IntFlag(定义于 Lib/inspect.py),表示传给实现了 buffer 协议对象 __buffer__ 方法的标志,语义详见 buffer 请求类型文档。成员包括:SIMPLE、WRITABLE、FORMAT、ND、STRIDES、C_CONTIGUOUS、F_CONTIGUOUS、ANY_CONTIGUOUS、INDIRECT、CONTIG、CONTIG_RO、STRIDED、STRIDED_RO、RECORDS、RECORDS_RO、FULL、FULL_RO、READ、WRITE。从源码可见其组合关系:STRIDES = 0x10 | ND、RECORDS_RO = STRIDES | FORMAT、FULL = INDIRECT | WRITABLE | FORMAT,可对照 Python/C API 层(Include/pybuffer.h 的 PyBUF_*)理解一一对应关系(3.12+)。
十一、命令行内省:python -m inspect
inspect 自带基础命令行能力(入口 _main() 见 Lib/inspect.py):
python -m inspect 模块名 # 打印模块源码
python -m inspect 模块:类.方法 # 打印模块内对象的源码
python -m inspect --details 目标 # 打印对象信息而非源码
用法细节:默认接受模块名并打印其源码;用冒号后跟目标对象的限定名可定位到模块内的类或函数。--details 选项打印对象信息而非源码。3.15 起 --details 对无可用源码的模块也能做基础内省、指出模块是否被冻结(frozen),并提示给定目标引用是否为对象规范名之外的别名。
CLI 实现要点(来自源码注释与逻辑):解析 module:qualname 语法后 importlib.import_module 再逐段 getattr(Lib/inspect.py);_get_details_for_cli 会通过 getmodule 判定目标是否定义于别的模块,若用户给出的名字只是别名/再导出名,则报告真正定义模块并以 alias 字段标注(Lib/inspect.py);无源码的 builtin 模块与普通模块分别给出对应错误信息。
十二、测试验证与深入研读指引
inspect 拥有独立成目录的测试套件 Lib/test/test_inspect/,其中 inspect_fodder.py(StupidGit → MalodorousPervert → FesteringGob 的多重继承链)、inspect_fodder2.py(覆盖 TypedDict、NamedTuple、Enum/IntFlag/Flag、dataclass 等泛型与特殊类)、inspect_fodder3.py(docstring 继承场景)为各 API 提供了可直接阅读的"标的物";另有 inspect_stock_annotations.py、inspect_stringized_annotations.py、inspect_stringized_annotations_pep695.py 等专门验证注解反字符串化与 PEP 695 类型参数行为。阅读 Lib/test/test_inspect/ 中对应主测试文件,是理解 signature() 在不同类对象(含 NamedTuple、泛型类、枚举)上的边界行为的最高效途径。
小结
inspect 的价值在于把 CPython 对象模型中的内部属性封装为稳定的公开 API:is* 谓词 + getmembers 解决"对象里有什么、是什么";getsource/getdoc 解决"对象源码与文档在哪";Signature 体系解决"怎么调用它"(参数绑定、默认值、注解、位置限制);栈探测函数解决"当前执行到哪里"。在框架层做参数校验、命令行工具生成帮助、IDE 补全与调试器实现时,inspect 往往是被依赖最深的标准库模块之一。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00