网易首页 > 网易号 > 正文 申请入驻

Python 标准库:dis(字节码反汇编与执行机制分析)

0
分享至

dis 是 Python 标准库中用于分析字节码的模块,可以将编译后的指令转换为便于阅读的形式,帮助观察变量访问、运算、函数调用和控制流程的实现方式。

它适合学习程序执行机制、比较不同写法的编译结果,以及辅助定位异常或分析性能问题。反汇编展示的是解释器层面的指令结构,不能直接代替运行测试和性能测量。

一、导入与常见应用场景

1、导入模块

dis 随 Python 提供,无需额外安装。

import dis

本文以 CPython 为分析对象。字节码属于解释器实现细节,指令名称、参数含义和输出格式可能随解释器版本变化,不应视为 Python 语言固定不变的规则。

2、常见应用场景

• 理解执行机制:观察表达式如何加载数据、执行运算并返回结果。

• 分析控制流程:查看条件分支、循环和短路求值对应的指令。

• 比较代码结构:分析不同写法生成的指令及代码对象信息。

• 观察编译优化:检查常量折叠等优化是否发生。

• 辅助调试:结合异常回溯定位发生错误的指令。

3、与相关模块的分工

• dis:分析编译后的字节码与相关信息。

• ast:分析源代码的语法结构。

• inspect:获取函数、类、参数和源码等对象信息。

• timeit:测量小段代码的执行时间。

• cProfile:分析程序运行过程中各函数的调用与耗时。

dis 主要回答“代码被编译成了什么结构”;执行频率和实际耗时通常需要其他工具测量。

二、核心概念

1、源代码、字节码与机器码

源代码(Source Code)是编写的 Python 文本。

在 CPython 的常规执行流程中,源代码经过解析和编译,形成包含字节码的代码对象,再由解释器执行。

字节码(Bytecode)是供解释器处理的指令表示,不等同于处理器直接执行的机器码(Machine Code)。dis 展示的是字节码层面的反汇编,而不是硬件汇编指令。

2、代码对象

代码对象(Code Object)保存编译后的指令及相关信息,例如常量、变量名称和源码位置。

普通 Python 函数通过 __code__ 属性关联代码对象:

代码对象与函数对象不同。函数还关联全局命名空间、默认参数和闭包等执行所需的信息。

3、指令与操作参数

一条字节码指令通常包含操作码(Opcode),并可能带有操作参数。

操作参数不一定是源代码中的数值,也可能表示常量索引、变量索引、运算类型或跳转信息。

阅读时应结合指令名称与参数解释,不宜单独根据参数数字推断作用。

4、求值栈

CPython 的许多指令通过求值栈(Evaluation Stack)传递中间结果。

例如,计算 a + b 时,可以从概念上理解为:

• 取得 a 和 b 的值。

• 执行加法,将结果作为新的中间值。

• 将结果返回给调用方。

实际输出可能将多个动作组合为一条指令,或采用专门化指令,因此不必强求每个源码动作都对应一条独立指令。

三、使用 dis.dis() 查看字节码

1、反汇编函数

dis.dis() 默认将反汇编结果写入标准输出,函数本身返回 None。

这里传入的是函数对象 add,不会调用该函数。若写成 dis.dis(add(2, 3)),则会先计算函数结果,再尝试对结果进行反汇编,通常不符合分析目的。

2、阅读输出中的信息

反汇编输出主要包含:

• 源码位置:指令对应的行号或更详细的位置。

• 逻辑标签:用于标记跳转目标等位置。

• 指令名称:说明该指令执行的操作。

• 操作参数:指令使用的数字参数。

• 参数解释:变量名、常量值、运算符或跳转目标等可读信息。

当前输出通常使用逻辑标签表示跳转目标。需要同时查看指令偏移量和更详细的源码位置时,可以使用:

偏移量用于定位字节码中的位置,不是源代码行号;源码位置与字节码指令也不一定一一对应。

3、理解常见指令类别

阅读输出时,可以先关注指令的作用类别:

• LOAD_CONST:加载常量。

• LOAD_FAST、LOAD_FAST_BORROW 等:访问局部变量,具体指令具有不同的内部语义。

• STORE_FAST:将值保存到局部变量。

• LOAD_GLOBAL:查找全局名称或内置名称。

• BINARY_OP:执行由参数指定的二元或原地操作。

• COMPARE_OP:执行比较操作。

• CALL:执行调用相关操作。

• RETURN_VALUE:返回栈顶结果。

这些名称只是阅读入口。实际代码还可能使用组合指令或特化指令,应以当前解释器的输出与对应定义为准。

4、分析源代码字符串

dis 会先编译字符串,再展示反汇编结果,不会执行其中的赋值和乘法。因此,分析时不要求 price 和 quantity 已经有值。

也可以显式创建代码对象:

eval 模式用于表达式,exec 模式用于语句序列。选择不同模式,生成的代码结构也可能不同。

5、控制嵌套代码的展开

depth=0 只显示当前代码对象,不递归展开其中的嵌套代码对象。

省略 depth 时,dis 会继续分析嵌套代码对象。这里控制的是反汇编展示的递归深度,不是程序运行时的递归限制。

四、结构化读取指令与代码信息

1、遍历 Instruction 对象

需要在程序中分析指令时,使用 get_instructions() 比解析打印文本更合适。

    

get_instructions() 返回迭代器,每次产生一个指令对象(Instruction)。

常用字段包括:

• offset:指令在字节码中的偏移位置。

• opname:可读的指令名称。

• opcode:操作码数值。

• arg:数字形式的操作参数,没有参数时为 None。

• argval:解析后的参数值。

• argrepr:参数的可读描述。

• is_jump_target:是否为其他指令的跳转目标。

2、查看源码位置

    

位置对象包含起止行号与列偏移。部分位置数据可能为 None,分析程序应考虑信息缺失的情况。

列偏移按源码的 UTF-8 字节偏移表示。源码包含中文等非 ASCII 字符时,不能直接将它当作 Python 字符串的字符索引切片。

3、查看代码对象摘要

结果通常包含函数名称、文件名、参数数量、局部变量数量、栈空间需求、常量和名称等信息。

也可以直接打印:

code_info() 返回字符串,show_code() 直接输出信息。

其中的栈空间信息描述求值栈所需的槽位,不表示函数调用次数、递归深度或内存字节数。

4、使用 Bytecode 对象

    

Bytecode 将常用分析功能组织在一个对象中:

• info():返回代码对象摘要字符串。

• dis():返回反汇编结果字符串。

• 迭代对象:逐项获取 Instruction。

因此,需要将反汇编结果保存到变量时,可使用 Bytecode.dis();不宜将 dis.dis() 的返回值当作结果文本。

五、分析条件、循环与编译优化

1、条件分支

阅读时可以依次寻找:

• score 与常量的加载。

• 比较操作。

• 根据比较结果决定执行路径的跳转。

• 各分支的返回操作。

反汇编列出的是可能执行的指令结构。一次函数调用通常只经过其中一条路径,不会按输出顺序执行所有分支。

2、循环结构

循环中通常可以观察到获取迭代器、取得下一项、更新累计值和返回循环位置等操作。

循环体的指令在反汇编中只出现一份,但运行时可能重复执行很多次。因此,静态指令数量不等于实际执行次数。

3、短路求值

or 会根据第一个操作数的真值决定是否需要取得第二个操作数。

该表达式返回某个操作数本身,不会统一转换为 True 或 False。可以结合跳转和返回位置观察这种选择行为。

4、常量折叠

在常见 CPython 编译结果中,纯常量表达式 2 + 3 * 4 会提前计算为 14;第二个函数中的 3 * 4 也可能提前合并为 12,而 value 相关的加法仍需要运行时执行。

这种编译期处理称为常量折叠(Constant Folding)。

它说明源代码中的每个运算符不一定对应一次运行时运算。具体优化范围由编译器决定,不能据此认为所有看似固定的表达式都会被提前计算。

六、运行时特化与内联缓存

1、观察运行后的指令形式

CPython 可以根据运行时情况,对部分操作采用更有针对性的执行形式,这类机制称为特化(Specialization)。

adaptive=True 用于显示可能经过运行时特化的字节码。

重复调用使解释器有机会观察操作数类型等信息,但不保证一定出现某种指令。特化结果受解释器实现、构建配置、调用历史和输入类型影响。

2、查看内联缓存

内联缓存(Inline Cache)用于保存解释器执行某些操作时可复用的信息,通常与前面的指令关联。

show_caches=True 会显示这些缓存条目。它们不是源代码中的独立语句,也不能简单按普通业务操作累计。

当前的 get_instructions() 不再将缓存条目作为独立 Instruction 返回;相关信息可通过指令对象的 cache_info 字段读取。不要将它与 dis.dis() 的缓存显示方式混为一谈。

3、分析结果的边界

默认反汇编与特化视图展示的层次不同。比较两段代码时,应明确是否启用了 adaptive 和缓存显示。

dis 不会提供完整的处理器机器码视图;运行时优化也可能超出普通字节码输出能够直接呈现的范围。

七、异常定位与命令行使用

1、根据异常回溯定位指令

    

Bytecode.from_traceback() 根据回溯创建分析对象,并标记引发异常的指令位置。

本例可将错误与除法操作联系起来。它提供的是指令位置,具体原因仍需要结合异常类型、输入数据和调用上下文判断。

2、在终端反汇编文件

将需要分析的代码保存为 example.py,然后运行:

该命令读取并编译源文件,输出反汇编结果,不会执行文件中的顶层业务代码。

常用选项包括:

• -C:显示内联缓存。

• -O:显示指令偏移量。

• -P:显示更详细的源码位置。

例如:

这里的 -O 位于 -m dis 之后,是 dis 的显示选项;python -O -m dis example.py 中的 -O 则是解释器的优化选项,两者作用不同。

3、保存反汇编结果

    

也可以将 dis.Bytecode(square).dis() 返回的字符串写入文件,便于归档或比较。

八、应用举例:比较两种列表构造方式

以下示例比较普通循环和列表推导式的编译结构,并将代码摘要、反汇编结果和指令名称统计保存为报告。

报告保存在 bytecode_report.txt,再次运行会覆盖同名文件。

阅读报告时,可以关注普通循环中的方法访问与调用,以及列表推导式中可能出现的 LIST_APPEND 等操作,理解两种写法的编译结构。

示例只统计各函数当前代码对象中的指令,不递归累计嵌套代码对象;运行时执行次数也不包含在该统计中。

如果需要比较耗时,可以在上述函数定义之后补充:

    

这些时间还包含函数调用及计时包装的开销,应在相同环境和相同输入下比较,并结合实际业务规模判断。

指令更少不一定意味着执行更快。一个调用指令可能触发大量底层工作,而数据类型、缓存状态和内存分配也会影响耗时。

九、常用函数与类速览

以下列出常用调用形式,省略部分可选参数。

• dis.dis(x):输出反汇编结果,返回 None。

• dis.dis(x, file=file):将反汇编结果写入指定文本流。

• dis.dis(x, depth=0):只分析当前层级,不递归展开嵌套代码对象。

• dis.dis(x, show_offsets=True):显示指令偏移量。

• dis.dis(x, show_positions=True):显示更详细的源码位置。

• dis.dis(x, adaptive=True):显示可能经过运行时特化的字节码。

• dis.dis(x, show_caches=True):显示内联缓存。

• dis.get_instructions(x):返回 Instruction 对象的迭代器。

• dis.code_info(x):返回代码对象摘要字符串。

• dis.show_code(x):直接输出代码对象摘要。

• dis.Bytecode(x):创建可迭代的字节码分析对象。

• Bytecode.dis():返回格式化的反汇编字符串。

• Bytecode.info():返回代码对象摘要字符串。

• dis.Bytecode.from_traceback(tb):根据异常回溯创建分析对象并标记相关指令。

• dis.stack_effect(opcode, oparg=None, *, jump=None):计算指令对求值栈深度的净影响。

十、补充说明

1、字节码与语言语义

Python 语言规定表达式和语句的行为,CPython 字节码描述某种具体实现。

学习时应先理解代码语义,再用反汇编观察实现,不宜将特定指令组合当作编写 Python 程序必须遵守的固定模式。

2、结构分析与性能判断

dis 展示指令结构,不记录每条指令实际执行了多少次,也不直接测量耗时。

发现可疑结构后,应结合 timeit、cProfile 或实际任务测试验证,再决定是否优化。

3、编译分析与代码执行

反汇编普通函数对象或编译源代码字符串,不会调用被分析的函数或执行业务语句。

但为了取得函数而导入模块时,模块顶层代码仍可能执行;特化示例中的重复调用和性能测量也会实际运行目标函数。

4、反汇编与源码恢复

dis 不能完整恢复原始源码。变量名和部分位置信息可能保留,但注释、排版以及某些源码结构已经在编译过程中丢失或改变。

因此,反汇编结果适合分析执行结构,不能替代源码备份或作为完整的反编译结果。

5、栈变化与执行成本

stack_effect() 返回的是某条指令对求值栈深度的净影响,不是执行时间或内存消耗。

对于存在跳转的指令,跳转与不跳转时的栈变化可能不同。计算整个函数的栈行为时,需要结合控制流程,不能简单将所有指令的结果相加。

小结

dis 将 CPython 字节码转换为可读指令,帮助理解变量访问、控制流程、编译优化和运行时特化。分析时应结合源码语义与解释器环境;涉及性能结论,还需通过计时或性能分析工具验证。


“点赞有美意,赞赏是鼓励”

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
一百万买一条命:判决书里,权力最大的人被隐去了名字

一百万买一条命:判决书里,权力最大的人被隐去了名字

卉姐
2026-10-27 11:50:47
日方收到通知,下个月没时间接待,中方要把时间留给更重要的事

日方收到通知,下个月没时间接待,中方要把时间留给更重要的事

共工之锚
2026-10-28 00:51:46
雷军卖房了?小米首个住宅小区开售!单价1.38万元,比周边楼盘低1000元至数千元,仅内部员工可购

雷军卖房了?小米首个住宅小区开售!单价1.38万元,比周边楼盘低1000元至数千元,仅内部员工可购

21世纪经济报道
2026-10-27 21:24:41
姆巴佩到底说了啥?一个“玩笑”引发的连锁反应,或遭商业反噬

姆巴佩到底说了啥?一个“玩笑”引发的连锁反应,或遭商业反噬

汪星人哟
2026-10-27 08:32:57
公路车骑行服,熟女骑行穿搭,利落面料勾勒饱满曲线

公路车骑行服,熟女骑行穿搭,利落面料勾勒饱满曲线

只要高兴就好
2026-09-24 11:58:50
菜市场部分猪头肉常温放四五天不发粘不变色?工人“揭秘”:煮之前加一小把亚硝酸钠

菜市场部分猪头肉常温放四五天不发粘不变色?工人“揭秘”:煮之前加一小把亚硝酸钠

闪电新闻
2026-10-27 21:49:22
女研究生患肠癌休学治疗一年重返校园,复查显示“无瘤生存” 曾边考研边照顾患癌母亲打动网友

女研究生患肠癌休学治疗一年重返校园,复查显示“无瘤生存” 曾边考研边照顾患癌母亲打动网友

红星新闻
2026-10-27 17:25:05
鲍鹏山:如果中国真的足够强大!我们没必要脆弱到那么害怕批评!

鲍鹏山:如果中国真的足够强大!我们没必要脆弱到那么害怕批评!

用冷眼洞悉世界
2026-06-24 00:44:14
姆巴佩遭全网封杀抵制原因曝光,一句玩笑让他彻底翻车

姆巴佩遭全网封杀抵制原因曝光,一句玩笑让他彻底翻车

映射生活的身影
2026-10-27 17:42:38
消失两年的反诈博主,都以为他“被抓了”,原来是被境外电诈金主买凶绑架后折磨致死了。

消失两年的反诈博主,都以为他“被抓了”,原来是被境外电诈金主买凶绑架后折磨致死了。

贴小君
2026-10-27 11:29:35
比销量下滑还可怕的是:连生活在县城的居民,都开始抛弃了油车?

比销量下滑还可怕的是:连生活在县城的居民,都开始抛弃了油车?

兴趣知识
2026-10-28 05:05:50
中英法三文发道歉信!姆巴佩就不当言论道歉:对中国怀有深深敬意

中英法三文发道歉信!姆巴佩就不当言论道歉:对中国怀有深深敬意

全景体育V
2026-10-27 20:15:51
养老金差距本质上是分配不公平,而不是谁缴费更多

养老金差距本质上是分配不公平,而不是谁缴费更多

马小白
2026-10-27 10:41:50
四姐妹都当失足女赚钱,嫌分赃不均,2012年三妹叫2个情夫杀大姐

四姐妹都当失足女赚钱,嫌分赃不均,2012年三妹叫2个情夫杀大姐

汉史趣闻
2026-10-27 19:04:42
国务院定调,减缓人工智能的应用。全都是机器人了,大量人工下岗,没有工作,没有收入,谁去消费?

国务院定调,减缓人工智能的应用。全都是机器人了,大量人工下岗,没有工作,没有收入,谁去消费?

扶苏聊历史
2026-10-26 16:14:21
姆巴佩道歉:我的言论欠妥绝非本意!对中国人民及其历史怀有深深敬意

姆巴佩道歉:我的言论欠妥绝非本意!对中国人民及其历史怀有深深敬意

念洲
2026-10-27 20:03:12
4-6大冷门,英超第2不敌低级别英乙第18,阿森纳无缘英联杯八强

4-6大冷门,英超第2不敌低级别英乙第18,阿森纳无缘英联杯八强

侧身凌空斩
2026-10-28 06:11:01
【环时深度】警惕!鲁比奥中亚行不只是“找矿”

【环时深度】警惕!鲁比奥中亚行不只是“找矿”

环球网资讯
2026-10-28 06:47:52
网传体制内已成网贷重灾区,网友说:他们工作收入太稳定了,是网贷的优质潜在客户!

网传体制内已成网贷重灾区,网友说:他们工作收入太稳定了,是网贷的优质潜在客户!

黯泉
2026-10-27 09:41:14
到了交房租的日子,租客不辞而别,留下了一张字条和277元现金,“身上实在没钱了,就剩这么多,都给你了”;房东:押金和277元全额退回

到了交房租的日子,租客不辞而别,留下了一张字条和277元现金,“身上实在没钱了,就剩这么多,都给你了”;房东:押金和277元全额退回

扬子晚报
2026-10-27 10:03:03
2026-10-28 08:35:00
MediaTea
MediaTea
专业的数字媒体、新媒体技术
2257文章数 85关注度
往期回顾 全部

科技要闻

M6芯片版14英寸MacBook Pro:15999元起

头条要闻

法国访谈节目《The Bridge》就姆巴佩事件道歉

头条要闻

法国访谈节目《The Bridge》就姆巴佩事件道歉

体育要闻

世界上最无趣的前锋,拿下了金球奖

娱乐要闻

芒果遇到厉娜和许飞笑发财了!

财经要闻

订单越厚,账单越重:算力租赁的杠杆游戏

汽车要闻

纯电续航1003km 大五座SUV腾势N8正式开启预订

态度原创

教育
家居
亲子
本地
游戏

教育要闻

人民日报: 家庭教育比学校教育更重要, 父母使命大于老师责任(老师转给家长)

家居要闻

2026建博会(广州) 公装联探展交流活动

亲子要闻

看我如何吃到妈妈的棒棒糖

本地新闻

十月奔赴迪庆,解锁梅里日照金山

《影之刃零》联名XR眼镜推出 售价599美元

无障碍浏览 进入关怀版