dis --- Python 字节码反汇编器¶
源代码: Lib/dis.py
dis 模块通过反汇编支持CPython的 bytecode 分析。该模块作为输入的 CPython 字节码在文件 Include/opcode.h 中定义,并由编译器和解释器使用。
CPython 实现细节: 字节码是 CPython 解释器的实现细节。不保证不会在Python版本之间添加、删除或更改字节码。不应考虑将此模块的跨 Python VM 或 Python 版本的使用。
在 3.6 版本发生变更: 每条指令使用2个字节。以前字节数因指令而异。
在 3.10 版本发生变更: 跳转、异常处理和循环指令的参数现在将为指令偏移量而不是字节偏移量。
示例:给出函数 myfunc():
def myfunc(alist):
return len(alist)
以下命令可被用来显示 myfunc() 的反汇编:
>>> dis.dis(myfunc)
2 0 RESUME 0
3 2 LOAD_GLOBAL 1 (NULL + len)
14 LOAD_FAST 0 (alist)
16 PRECALL 1
20 CALL 1
30 RETURN_VALUE
("2" 是行号)。
命令行接口¶
dis 模块可以在命令行下作为一个脚本来唤起:
python -m dis [-h] [-C] [infile]
可以接受以下选项:
- -h, --help¶
显示用法并退出。
- -C, --show-caches¶
显示内联缓存。
如果指定了 infile,其反汇编代码将被写入到标准输出。 否则,反汇编将在从标准输入接收的已编译源代码上进行。
字节码分析¶
在 3.4 版本加入.
字节码分析 API 允许将 Python 代码片段包装在 Bytecode 对象中,以便轻松访问已编译代码的详细信息。
- class dis.Bytecode(x, *, first_line=None, current_offset=None, show_caches=False, adaptive=False)¶
分析的字节码对应于函数、生成器、异步生成器、协程、方法、源代码字符串或代码对象(由
compile()返回)。这是下面列出的许多函数的便利包装,最值得注意的是
get_instructions(),迭代于Bytecode的实例产生字节码操作Instruction的实例。如果 first_line 不是
None,则表示应该为反汇编代码中的第一个源代码行报告的行号。否则,源行信息(如果有的话)直接来自反汇编的代码对象。如果 current_offset 不是
None,它指的就是汇编代码中的指令偏移量。设置它意味着dis()将针对指定的操作码显示“当前指令”标记。如果 show_caches 为
True,dis()将显示解释器用来专门化字节码的内联缓存条目。如果 adaptive 为
True,dis()将显示可能不同于原始字节码的专门化字节码。- classmethod from_traceback(tb, *, show_caches=False)¶
从给定回溯构造一个
Bytecode实例,将设置 current_offset 为异常负责的指令。
- codeobj¶
已编译的代码对象。
- first_line¶
代码对象的第一个源代码行(如果可用)
- info()¶
返回带有关于代码对象的详细信息的格式化多行字符串,如
code_info()。
在 3.7 版本发生变更: 现在可以处理协程和异步生成器对象。
在 3.11 版本发生变更: 增加了 show_caches 和 adaptive 形参。
示例:
>>> bytecode = dis.Bytecode(myfunc)
>>> for instr in bytecode:
... print(instr.opname)
...
RESUME
LOAD_GLOBAL
LOAD_FAST
PRECALL
CALL
RETURN_VALUE
分析函数¶
dis 模块还定义了以下分析函数,它们将输入直接转换为所需的输出。如果只执行单个操作,它们可能很有用,因此中间分析对象没用:
- dis.code_info(x)¶
返回格式化的多行字符串,其包含详细代码对象信息的用于被提供的函数、生成器、异步生成器、协程、方法、源代码字符串或代码对象。
请注意,代码信息字符串的确切内容是高度依赖于实现的,它们可能会在Python VM或Python版本中任意更改。
在 3.2 版本加入.
在 3.7 版本发生变更: 现在可以处理协程和异步生成器对象。
- dis.show_code(x, *, file=None)¶
将提供的函数、方法。源代码字符串或代码对象的详细代码对象信息打印到 file (如果未指定 file ,则为
sys.stdout)。这是
print(code_info(x), file=file)的便捷简写,用于在解释器提示符下进行交互式探索。在 3.2 版本加入.
在 3.4 版本发生变更: 添加 file 形参。
- dis.dis(x=None, *, file=None, depth=None, show_caches=False, adaptive=False)¶
反汇编 x 对象。 x 可以表示模块、类、方法、函数、生成器、异步生成器、协程、代码对象、源代码字符串或原始字节码的字节序列。对于模块,它会反汇编所有功能。对于一个类,它反汇编所有方法(包括类和静态方法)。对于代码对象或原始字节码序列,它每字节码指令打印一行。它还递归地反汇编嵌套代码对象(推导式代码,生成器表达式和嵌套函数,以及用于构建嵌套类的代码)。在被反汇编之前,首先使用
compile()内置函数将字符串编译为代码对象。如果未提供任何对象,则此函数会反汇编最后一次回溯。如果提供的话,反汇编将作为文本写入提供的 file 参数,否则写入
sys.stdout。递归的最大深度受 depth 限制,除非它是
None。depth=0表示没有递归。如果 show_caches 为
True,此函数将显示解释器用来专门化字节码的内联缓存条目。如果 adaptive 为
True,此函数将显示可能不同于原始字节码的专门化字节码。在 3.4 版本发生变更: 添加 file 形参。
在 3.7 版本发生变更: 实现了递归反汇编并添加了 depth 参数。
在 3.7 版本发生变更: 现在可以处理协程和异步生成器对象。
在 3.11 版本发生变更: 增加了 show_caches 和 adaptive 形参。
- dis.distb(tb=None, *, file=None, show_caches=False, adaptive=False)¶
如果没有传递,则使用最后一个回溯来反汇编回溯的堆栈顶部函数。 指示了导致异常的指令。
如果提供的话,反汇编将作为文本写入提供的 file 参数,否则写入
sys.stdout。在 3.4 版本发生变更: 添加 file 形参。
在 3.11 版本发生变更: 增加了 show_caches 和 adaptive 形参。
- dis.disassemble(code, lasti=-1, *, file=None, show_caches=False, adaptive=False)¶
- dis.disco(code, lasti=-1, *, file=None, show_caches=False, adaptive=False)¶
反汇编代码对象,如果提供了 lasti ,则指示最后一条指令。输出分为以下几列:
行号,用于每行的第一条指令
当前指令,表示为
-->,一个标记的指令,用
>>表示,指令的地址,
操作码名称,
操作参数,和
括号中参数的解释。
参数解释识别本地和全局变量名称、常量值、分支目标和比较运算符。
如果提供的话,反汇编将作为文本写入提供的 file 参数,否则写入
sys.stdout。在 3.4 版本发生变更: 添加 file 形参。
在 3.11 版本发生变更: 增加了 show_caches 和 adaptive 形参。
- dis.get_instructions(x, *, first_line=None, show_caches=False, adaptive=False)¶
在所提供的函数、方法、源代码字符串或代码对象中的指令上返回一个迭代器。
迭代器生成一系列
Instruction,命名为元组,提供所提供代码中每个操作的详细信息。如果 first_line 不是
None,则表示应该为反汇编代码中的第一个源代码行报告的行号。否则,源行信息(如果有的话)直接来自反汇编的代码对象。show_caches 和 adaptive 形参的作用与
dis()中的同名形参相同。在 3.4 版本加入.
在 3.11 版本发生变更: 增加了 show_caches 和 adaptive 形参。
- dis.findlinestarts(code)¶
这个生成器函数使用 代码对象 code 的
co_lines()方法来查找源代码中行开头的偏移量。 它们将作为(offset, lineno)对被生成。在 3.6 版本发生变更: 行号可能会减少。 以前,他们总是在增加。
在 3.10 版本发生变更: 使用 PEP 626
co_lines()方法而不是 代码对象 的co_firstlineno和co_lnotab属性。
- dis.findlabels(code)¶
检测作为跳转目标的原始编译后字节码字符串 code 中的所有偏移量,并返回这些偏移量的列表。
- dis.stack_effect(opcode, oparg=None, *, jump=None)¶
使用参数 oparg 计算 opcode 的堆栈效果。
如果代码有一个跳转目标并且 jump 是
True,则drag_effect()将返回跳转的堆栈效果。如果 jump 是False,它将返回不跳跃的堆栈效果。如果 jump 是None(默认值),它将返回两种情况的最大堆栈效果。在 3.4 版本加入.
在 3.8 版本发生变更: 添加 jump 参数。
Python字节码说明¶
get_instructions() 函数和 Bytecode 类提供字节码指令的详细信息的 Instruction 实例:
- class dis.Instruction¶
字节码操作的详细信息
- opname¶
人类可读的操作名称
- arg¶
操作的数字参数(如果有的话),否则为
None
- argval¶
已解析的 arg 值(如果有的话),否则为
None
- argrepr¶
人类可读的操作参数(如果存在)的描述,否则为空字符串。
- offset¶
在字节码序列中的起始操作索引
- starts_line¶
行由此操作码(如果有)启动,否则为
None
- is_jump_target¶
如果其他代码跳到这里,则为
True,否则为False
- positions¶
dis.Positions对象保存了这条指令所涵盖的起始和结束位置。
在 3.4 版本加入.
在 3.11 版本发生变更: 增加了
positions字段。
- class dis.Positions¶
考虑到此信息不可用的情况,某些字段可能为
None。- lineno¶
- end_lineno¶
- col_offset¶
- end_col_offset¶
在 3.11 版本加入.
Python编译器当前生成以下字节码指令。
一般指令
- NOP¶
无操作代码。 被字节码优化器用作占位符,以及生成行追踪事件。
- POP_TOP¶
删除堆栈顶部(TOS)项。
- COPY(i)¶
将第 i 项推入栈顶。 该项不会从其原始位置移除。
在 3.11 版本加入.
- SWAP(i)¶
将 TOS 与位置 i 处的项交换。
在 3.11 版本加入.
- CACHE¶
此操作码不是真正的指令,它被用来为解释器标记额外空间以便在字节码中直接缓存有用的数据。 它会被所有
dis工具自动隐藏,但可以通过show_caches=True来查看。从逻辑上说,此空间是之前的指令的组成部分。 许多操作码都预期带有固定数量的缓存,并会指示解释器在运行时跳过它们。
被填充的缓存看起来可以像是任意的指令,因此在读取或修改包含快取数据的原始自适应字节码时应当非常小心。
在 3.11 版本加入.
一元操作
一元操作获取堆栈顶部元素,应用操作,并将结果推回堆栈。
- UNARY_POSITIVE¶
实现
TOS = +TOS。
- UNARY_NEGATIVE¶
实现
TOS = -TOS。
- UNARY_NOT¶
实现
TOS = not TOS。
- UNARY_INVERT¶
实现
TOS = ~TOS。
- GET_ITER¶
实现
TOS = iter(TOS)。
- GET_YIELD_FROM_ITER¶
如果
TOS是一个 generator iterator 或 coroutine 对象则保持原样。否则实现TOS = iter(TOS)。在 3.5 版本加入.
双目和原地操作
二元操作从堆栈中删除堆栈顶部(TOS)和第二个最顶层堆栈项(TOS1)。 它们执行操作,并将结果放回堆栈。
就地操作就像二元操作,因为它们删除了TOS和TOS1,并将结果推回到堆栈上,但是当TOS1支持它时,操作就地完成,并且产生的TOS可能是(但不一定) 原来的TOS1。
- BINARY_OP(op)¶
实现二元和就地运算符(取决于 op 的值)。
在 3.11 版本加入.
- BINARY_SUBSCR¶
实现
TOS = TOS1[TOS]。
- STORE_SUBSCR¶
实现
TOS1[TOS] = TOS2。
- DELETE_SUBSCR¶
实现
del TOS1[TOS]。
协程操作码
- GET_AWAITABLE(where)¶
实现
TOS = get_awaitable(TOS),其中get_awaitable(o)返回o如果o是一个有 CO_ITERABLE_COROUTINE 标志的协程对象或生成器对象,否则解析o.__await__。如果
where操作数为非零值,则表示指令所在的位置:1在调用__aenter__之后2在调用__aexit__之后
在 3.5 版本加入.
在 3.11 版本发生变更: 在之前版本中,该指令没有 oparg。
- GET_AITER¶
实现
TOS = TOS.__aiter__()。在 3.5 版本加入.
在 3.7 版本发生变更: 已经不再支持从
__aiter__返回可等待对象。
- GET_ANEXT¶
将
get_awaitable(TOS.__anext__())推入栈。 请参阅GET_AWAITABLE了解有关get_awaitable的详情。在 3.5 版本加入.
- END_ASYNC_FOR¶
终止
async for循环。 处理在等待下一项时引发的异常。 栈中在 TOS1 处包含异步可迭代对象,在 TOS 处包含所引发的异常。 两者都会被弹出。 如果该异常不是StopAsyncIteration,则会重新引发它。在 3.8 版本加入.
在 3.11 版本发生变更: 栈中的异常表示形式现在将由一个而不是三个条目组成。
- BEFORE_ASYNC_WITH¶
从栈顶对象解析
__aenter__和__aexit__。将__aexit__和__aenter__()的结果推入堆栈。在 3.5 版本加入.
其他操作码
- SET_ADD(i)¶
调用
set.add(TOS1[-i], TOS)。 用于实现集合推导。
- LIST_APPEND(i)¶
调用
list.append(TOS1[-i], TOS)。 用于实现列表推导式。
- MAP_ADD(i)¶
调用
dict.__setitem__(TOS1[-i], TOS1, TOS)。 用于实现字典推导。在 3.1 版本加入.
在 3.8 版本发生变更: 映射值为 TOS ,映射键为 TOS1 。之前,它们被颠倒了。
对于所有 SET_ADD 、 LIST_APPEND 和 MAP_ADD 指令,当弹出添加的值或键值对时,容器对象保留在堆栈上,以便它可用于循环的进一步迭代。
- RETURN_VALUE¶
返回 TOS 到函数的调用者。
- SETUP_ANNOTATIONS¶
检查
__annotations__是否在locals()中定义,如果没有,它被设置为空dict。只有在类或模块体静态地包含 variable annotations 时才会发出此操作码。在 3.6 版本加入.
- IMPORT_STAR¶
将所有不以
'_'开头的符号直接从模块 TOS 加载到局部命名空间。加载所有名称后弹出该模块。这个操作码实现了from module import *。
- POP_EXCEPT¶
从栈中弹出一个值,它将被用来恢复异常状态。
在 3.11 版本发生变更: 栈中的异常表示形式现在将由一个而不是三个条目组成。
- RERAISE¶
重新引发当前位于栈顶的异常。 如果 oparg 为非零值,则从栈顶额外弹出一个值用来设置当前帧的
f_lasti。在 3.9 版本加入.
在 3.11 版本发生变更: 栈中的异常表示形式现在将由一个而不是三个条目组成。
- PUSH_EXC_INFO¶
从栈中弹出一个值。 将当前异常推入栈顶。 将原先被弹出的值推回栈。 在异常处理器中使用。
在 3.11 版本加入.
- CHECK_EXC_MATCH¶
为
except执行异常匹配。 测试 TOS1 是否为匹配 TOS 的异常。 弹出 TOS 并推入测试的布尔结果。在 3.11 版本加入.
- CHECK_EG_MATCH¶
为
except*执行异常匹配。 对代表 TOS1 的异常组应用split(TOS)。在匹配的情况下,从栈中弹出两项并推入不匹配的子分组 (如完全匹配则为
None) 以及匹配的子分组。 当没有任何匹配时,则弹出一项 (匹配类型) 并推入None。在 3.11 版本加入.
- PREP_RERAISE_STAR¶
将来自 TOS 的引发和重新引发的异常列表合并为一个异常组,以便从 try-except* 块向外传播。 使用来自 TOS1 的原始异常组来重构重新引发的异常的结构。 从栈中弹出两项,并推入要重新引发的异常(如果没有则推入
None)。在 3.11 版本加入.
- WITH_EXCEPT_START¶
调用栈中 4 号位置上的函数并附带代表位于栈顶的异常的参数 (type, val, tb)。 用于在
with语句内发生异常时实现调用context_manager.__exit__(*exc_info())。在 3.9 版本加入.
在 3.11 版本发生变更:
__exit__函数位于栈的 4 号位而不是 7 号位。 栈中的异常表示形式现在由一项而不是三项组成。
- LOAD_ASSERTION_ERROR¶
将
AssertionError推入栈顶。 由assert语句使用。在 3.9 版本加入.
- LOAD_BUILD_CLASS¶
将
builtins.__build_class__()推入栈。 之后它将会被调用来构造一个类。
- BEFORE_WITH(delta)¶
此操作码会在 with 代码块开始之前执行多个操作。 首先,它将从上下文管理器加载
__exit__()并将其推入栈顶以供WITH_EXCEPT_START后续使用。 然后,将调用__enter__()。 最后,将调用__enter__()方法的结果推入栈顶。在 3.11 版本加入.
- GET_LEN¶
将
len(TOS)推入栈顶。在 3.10 版本加入.
- MATCH_MAPPING¶
如果 TOS 是
collections.abc.Mapping的实例(或者更严格地说:如果在它的tp_flags中设置了Py_TPFLAGS_MAPPING旗标),则将True推入栈。 否则推入False。在 3.10 版本加入.
- MATCH_SEQUENCE¶
如果 TOS 是
collections.abc.Sequence的实例且 不是str/bytes/bytearray的实例(或者更严格地说:如果在它的tp_flags中设置了Py_TPFLAGS_SEQUENCE旗标),则将True推入栈。 否则推入False。在 3.10 版本加入.
- MATCH_KEYS¶
TOS 是一个映射键组成的元组,而 TOS1 是匹配目标。 如果 TOS1 包含 TOS 中的所有键,则推入一个包含相应值的
tuple。 否则推入None。在 3.10 版本加入.
在 3.11 版本发生变更: 在之前的版本中,该指令还会推入一个表示成功 (
True) 或失败 (False) 的布尔值。
- STORE_NAME(namei)¶
实现
name = TOS。 namei 是 name 在 代码对象 的co_names属性中的索引。 编译器会尽可能尝试使用STORE_FAST或STORE_GLOBAL。
- UNPACK_SEQUENCE(count)¶
将 TOS 解包为 count 个单独的值,它们将按从右至左的顺序被放入堆栈。
- UNPACK_EX(counts)¶
实现使用带星号的目标进行赋值:将 TOS 中的可迭代对象解包为单独的值,其中值的总数可以小于可迭代对象中的项数:新值之一将是由所有剩余项构成的列表。
counts 的低字节是列表值之前的值的数量,counts 中的高字节则是之后的值的数量。 结果值会按从右至左的顺序入栈。
- STORE_ATTR(namei)¶
实现
TOS.name = TOS1,其中 namei 是 name 在co_names中的索引号。
- STORE_GLOBAL(namei)¶
类似于
STORE_NAME但会将 name 存储为全局变量。
- DELETE_GLOBAL(namei)¶
类似于
DELETE_NAME但会删除一个全局变量。
- LOAD_CONST(consti)¶
将
co_consts[consti]推入栈顶。
- LOAD_NAME(namei)¶
将与
co_names[namei]相关联的值推入栈顶。
- BUILD_TUPLE(count)¶
创建一个使用了来自栈的 count 个项的元组,并将结果元组推入栈顶。
- BUILD_LIST(count)¶
类似于
BUILD_TUPLE但会创建一个列表。
- BUILD_SET(count)¶
类似于
BUILD_TUPLE但会创建一个集合。
- BUILD_MAP(count)¶
将一个新字典对象推入栈顶。 弹出
2 * count项使得字典包含 count 个条目:{..., TOS3: TOS2, TOS1: TOS}。在 3.5 版本发生变更: 字典是根据栈中的项创建而不是创建一个预设大小包含 count 项的空字典。
- BUILD_CONST_KEY_MAP(count)¶
BUILD_MAP版本专用于常量键。 弹出的栈顶元素包含一个由键构成的元组,然后从TOS1开始从构建字典的值中弹出 count 个值。在 3.6 版本加入.
- BUILD_STRING(count)¶
拼接 count 个来自栈的字符串并将结果字符串推入栈顶。
在 3.6 版本加入.
- LIST_TO_TUPLE¶
从堆栈中弹出一个列表并推入一个包含相同值的元组。
在 3.9 版本加入.
- LIST_EXTEND(i)¶
调用
list.extend(TOS1[-i], TOS)。 用于构建列表。在 3.9 版本加入.
- SET_UPDATE(i)¶
调用
set.update(TOS1[-i], TOS)。 用于构建集合。在 3.9 版本加入.
- DICT_UPDATE(i)¶
调用
dict.update(TOS1[-i], TOS)。 用于构建字典。在 3.9 版本加入.
- DICT_MERGE(i)¶
类似于
DICT_UPDATE但对于重复的键会引发异常。在 3.9 版本加入.
- LOAD_ATTR(namei)¶
将 TOS 替换为
getattr(TOS, co_names[namei])。
- COMPARE_OP(opname)¶
执行布尔运算操作。 操作名称可在
cmp_op[opname]中找到。
- IS_OP(invert)¶
执行
is比较,或者如果invert为 1 则执行is not。在 3.9 版本加入.
- CONTAINS_OP(invert)¶
执行
in比较,或者如果invert为 1 则执行not in。在 3.9 版本加入.
- IMPORT_NAME(namei)¶
导入模块
co_names[namei]。 会弹出 TOS 和 TOS1 以提供 fromlist 和 level 参数给__import__()。 模块对象会被推入栈顶。 当前命名空间不受影响:对于一条标准 import 语句,会执行后续的STORE_FAST指令来修改命名空间。
- IMPORT_FROM(namei)¶
从在 TOS 内找到的模块中加载属性
co_names[namei]。 结果对象会被推入栈顶,以便由后续的STORE_FAST指令来保存。
- JUMP_FORWARD(delta)¶
将字节码计数器的值增加 delta。
- JUMP_BACKWARD(delta)¶
将字节码计数器减少 delta。 检查中断。
在 3.11 版本加入.
- JUMP_BACKWARD_NO_INTERRUPT(delta)¶
将字节码计数器减少 delta。 不检查中断。
在 3.11 版本加入.
- POP_JUMP_FORWARD_IF_TRUE(delta)¶
如果 TOS 为真值,则将字节码计数器的值增加 delta。 TOS 会被弹出。
在 3.11 版本加入.
- POP_JUMP_BACKWARD_IF_TRUE(delta)¶
如果 TOS 为真值,则将字节码计数器的值减少 delta。 TOS 会被弹出。
在 3.11 版本加入.
- POP_JUMP_FORWARD_IF_FALSE(delta)¶
如果 TOS 为假值,则将字节码计数器的值增加 delta。 TOS 会被弹出。
在 3.11 版本加入.
- POP_JUMP_BACKWARD_IF_FALSE(delta)¶
如果 TOS 为假值,则将字节码计数器的值减少 delta。 TOS 会被弹出。
在 3.11 版本加入.
- POP_JUMP_FORWARD_IF_NOT_NONE(delta)¶
如果 TOS 不为
None,则将字节码计数器的值增加 delta。 TOS 会被弹出。在 3.11 版本加入.
- POP_JUMP_BACKWARD_IF_NOT_NONE(delta)¶
如果 TOS 不为
None,则将字节码计数器的值减少 delta。 TOS 会被弹出。在 3.11 版本加入.
- POP_JUMP_FORWARD_IF_NONE(delta)¶
如果 TOS 为
None,则将字节码计数器的值增加 delta。 TOS 会被弹出。在 3.11 版本加入.
- POP_JUMP_BACKWARD_IF_NONE(delta)¶
如果 TOS 为
None,则将字节码计数器的值减少 delta。 TOS 会被弹出。在 3.11 版本加入.
- JUMP_IF_TRUE_OR_POP(delta)¶
如果 TOS 为真值,则将字节码计数器的值增加 delta 并将 TOS 保留在栈上。 否则(TOS 为假值),TOS 会被弹出。
在 3.1 版本加入.
在 3.11 版本发生变更: oparg 现在是一个相对增量而不是绝对目标。
- JUMP_IF_FALSE_OR_POP(delta)¶
如果 TOS 为假值,则将字节码计数器的值增加 delta 并将 TOS 保留在栈上。 否则(TOS 为真值),TOS 会被弹出。
在 3.1 版本加入.
在 3.11 版本发生变更: oparg 现在是一个相对增量而不是绝对目标。
- FOR_ITER(delta)¶
TOS 是一个 iterator。 请调用其
__next__()方法。 如果此操作产生了一个新值,则将其推入栈顶(将迭代器留在其下方)。 如果迭代器提示已耗尽,TOS 会被弹出,并且字节码计数器将增加 delta。
- LOAD_GLOBAL(namei)¶
将名为
co_names[namei>>1]的全局对象加载到栈顶。在 3.11 版本发生变更: 如果设置了
namei的低比特位,则会在全局变量前将一个NULL推入栈。
- LOAD_FAST(var_num)¶
将指向局部对象
co_varnames[var_num]的引用推入栈顶。
- STORE_FAST(var_num)¶
将 TOS 存放到局部对象
co_varnames[var_num]。
- DELETE_FAST(var_num)¶
移除局部对象
co_varnames[var_num]。
- MAKE_CELL(i)¶
在槽位
i中创建一个新单元。 如果该槽位为非空则该值将存储到新单元中。在 3.11 版本加入.
- LOAD_CLOSURE(i)¶
推入一个指向包含在 "fast locals" 存储的
i号槽位的单元的引用。 变量名为co_fastlocalnames[i]。注意
LOAD_CLOSURE实际上是LOAD_FAST的一个别名。 它的存在是为了让字节码的可读性更好一些。在 3.11 版本发生变更:
i不再是长度为co_varnames的偏移量。
- LOAD_DEREF(i)¶
加载包含在 "fast locals" 存储的
i号槽位中的单元。 将一个指向该单元所包含对象的引用推入栈。在 3.11 版本发生变更:
i不再是co_varnames的长度的偏移量。
- LOAD_CLASSDEREF(i)¶
类似于
LOAD_DEREF但在查询单元之前会首先检查局部对象字典。 这被用于加载类语句体中的自由变量。在 3.4 版本加入.
在 3.11 版本发生变更:
i不再是长度为co_varnames的偏移量。
- STORE_DEREF(i)¶
将 TOS 存放到包含在 "fast locals" 存储的
i号槽位中的单元内。在 3.11 版本发生变更:
i不再是co_varnames的长度的偏移量。
- DELETE_DEREF(i)¶
清空 "fast locals" 存储中包含在
i号槽位的单元。 被用于del语句。在 3.2 版本加入.
在 3.11 版本发生变更:
i不再是co_varnames的长度的偏移量。
- COPY_FREE_VARS(n)¶
将
n个自由变量从闭包拷贝到帧中。 当调用闭包时不再需要调用方添加特殊的代码。在 3.11 版本加入.
- RAISE_VARARGS(argc)¶
使用
raise语句的 3 种形式之一引发异常,具体形式取决于 argc 的值:0:
raise(重新引发之前的异常)1:
raise TOS(在TOS上引发异常实例或类型)2:
raise TOS1 from TOS(在TOS1上引发异常实例或类型并将__cause__设为TOS)
- CALL(argc)¶
调用一个可调用对象并传入由
argc所指定数量的参数,包括之前的KW_NAMES所指定的关键字参数,如果有的话。 在栈上(按升序排列),可以是:NULL
可调用对象
位置参数
关键字参数
或者:
可调用对象
self其余的位置参数
关键字参数
argc是位置和关键字参数的总和,当未提供NULL时将排除self。CALL将把所有参数和可调用对象弹出栈,附带这些参数调用该可调用对象,并将该可调用对象的返回值推入栈。在 3.11 版本加入.
- CALL_FUNCTION_EX(flags)¶
调用一个可调用对象并附带位置参数和关键字参数变量集合。 如果设置了 flags 的最低位,则栈顶包含一个由额外关键字参数组成的映射对象。 在调用该可调用对象之前,映射对象和可迭代对象会被分别“解包”并将它们的内容分别作为关键字参数和位置参数传入。
CALL_FUNCTION_EX会中栈中弹出所有参数及可调用对象,附带这些参数调用该可调用对象,并将可调用对象所返回的返回值推入栈顶。在 3.6 版本加入.
- LOAD_METHOD(namei)¶
从 TOS 对象加载名为
co_names[namei]的方法。 TOS 会被弹出。 此字节码区分两种情况:如果 TOS 具有正确名称的方法,该字节码会推入未绑定方法和 TOS。 在调用未绑定方法时,TOS 将被CALL用作第一个参数 (self)。 否则,将推入NULL以及由属性查找所返回的对象。在 3.7 版本加入.
- PUSH_NULL¶
将一个
NULL推入栈。 在调用序列中用来匹配LOAD_METHOD针对非方法调用推入栈的NULL。在 3.11 版本加入.
- KW_NAMES(i)¶
作为
PRECALL的前缀。 将指向co_consts[consti]的引用存储到内部变量中以供CALL使用。co_consts[consti]必须是一个字符串元组。在 3.11 版本加入.
- MAKE_FUNCTION(flags)¶
将一个新函数对象推入栈顶。 从底端到顶端,如果参数带有指定的旗标值则所使用的栈必须由这些值组成。
0x01一个默认值的元组,用于按位置排序的仅限位置形参以及位置或关键字形参0x02一个仅限关键字形参的默认值的字典0x04一个包含形参标注的字符串元组。0x08一个包含用于自由变量的单元的元组,生成一个闭包与函数关联的代码(位于 TOS)
在 3.10 版本发生变更: 旗标值
0x04是一个字符串元组而非字典。在 3.11 版本发生变更: 移除了位于 TOS 的限定名称。
- BUILD_SLICE(argc)¶
将一个切片对象推入栈顶。 argc 必须为 2 或 3。 如果为 2,则推入
slice(TOS1, TOS);如果为 3,则推入slice(TOS2, TOS1, TOS)。 请参阅slice()内置函数了解详细信息。
- EXTENDED_ARG(ext)¶
为任意带有大到无法放入默认的单字节的参数的操作码添加前缀。 ext 存放一个附加字节作为参数中的高比特位。 对于每个操作码,最多允许三个
EXTENDED_ARG前缀,构成两字节到三字节的参数。
- FORMAT_VALUE(flags)¶
用于实现格式化字面值字符串(f-字符串)。 从栈中弹出一个可选的 fmt_spec,然后是一个必须的 value。 flags 的解读方式如下:
(flags & 0x03) == 0x00: value 按原样格式化。(flags & 0x03) == 0x01: 在格式化 value 之前调用其str()。(flags & 0x03) == 0x02: 在格式化 value 之前调用其repr()。(flags & 0x03) == 0x03: 在格式化 value 之前调用其ascii()。(flags & 0x04) == 0x04: 从栈中弹出 fmt_spec 并使用它,否则使用空的 fmt_spec。
使用
PyObject_Format()执行格式化。 结果会被推入栈顶。在 3.6 版本加入.
- MATCH_CLASS(count)¶
TOS 是一个包含关键字属性名称的元组,TOS1 是要匹配的类,而 TOS2 是匹配目标。 count 是位置子模式的数量。
弹出 TOS、 TOS1 和 TOS2。 如果 TOS2 是 TOS1 的实例,并且具有 count 和 TOS 所要求的位置和关键字属性,则推入一个由提取出的属性组成的元组。 否则推入
None。在 3.10 版本加入.
在 3.11 版本发生变更: 在之前的版本中,该指令还会推入一个表示成功 (
True) 或失败 (False) 的布尔值。
- RESUME(where)¶
空操作。 执行内部追踪、调试和优化检查。
where操作数标记RESUME在哪里发生:0函数的开头1在yield表达式之后2在yield from表达式之后3在await表达式之后
在 3.11 版本加入.
- RETURN_GENERATOR¶
从当前帧创建一个生成器、协程或异步生成器。 清空当前帧并返回新创建的生成器。
在 3.11 版本加入.
- SEND¶
向此生成器的子生成器发送
None。 用于yield from和await语句。在 3.11 版本加入.
- ASYNC_GEN_WRAP¶
将栈顶的值包装在一个
async_generator_wrapped_value中。 用于在异步生成器中进行 yield。在 3.11 版本加入.
- HAVE_ARGUMENT¶
这不是一个真正的操作码。 它标明了不使用参数和使用参数的操作码 (分别是
< HAVE_ARGUMENT和>= HAVE_ARGUMENT) 之间的分隔线。在 3.6 版本发生变更: 现在每条指令都带有参数,但操作码
< HAVE_ARGUMENT会忽略它。 之前仅限操作码>= HAVE_ARGUMENT带有参数。
操作码集合¶
提供这些集合用于字节码指令的自动内省:
- dis.opname¶
操作名称的序列,可使用字节码来索引。
- dis.opmap¶
映射操作名称到字节码的字典
- dis.cmp_op¶
所有比较操作名称的序列。
- dis.hasconst¶
访问常量的字节码序列。
- dis.hasfree¶
访问自由变量的字节码序列(请注意这里所说的‘自由’是指在当前作用域中被内部作用域所引用的名称,或在外部作用域中被此作用域所引用的名称。 它 并不 包括对全局或内置作用域的引用)。
- dis.hasname¶
按名称访问属性的字节码序列。
- dis.hasjrel¶
具有相对跳转目标的字节码序列。
- dis.hasjabs¶
具有绝对跳转目标的字节码序列。
- dis.haslocal¶
访问局部变量的字节码序列。
- dis.hascompare¶
布尔运算的字节码序列。