Python使用dis模块把Python反编译为字节码的用法详解


Posted in Python onJune 14, 2016

dis — Disassembler for Python bytecode,即把python代码反汇编为字节码指令.
使用超级简单:

python -m dis xxx.py

Python 代码是先被编译为字节码后,再由Python虚拟机来执行字节码, Python的字节码是一种类似汇编指令的中间语言, 一个Python语句会对应若干字节码指令,虚拟机一条一条执行字节码指令, 从而完成程序执行。
Python dis 模块支持对Python代码进行反汇编, 生成字节码指令。
当我在网上看到while 1比while True快的时候,我感到很困惑,为何会有这种区别呢?
于是使用dis来深入.
假设est_while.py代码如下.

#coding=utf-8 
while 1: 
 pass 
 
while True: 
 pass

下面是使用dis来进行剖析.

E:\>python -m dis test_while.py 
 2   0 SETUP_LOOP    3 (to 6) 
 
 3  >> 3 JUMP_ABSOLUTE   3 
 
 5  >> 6 SETUP_LOOP    10 (to 19) 
  >> 9 LOAD_NAME    0 (True) 
    12 POP_JUMP_IF_FALSE  18

可以看到,在while 1这里(第3行),直接是JUMP_ABSOLUTE指令;
而while True这里(第5行),由LOAD_NAME和POP_JUMP_IF_FALSE指令组成.
原来True在python2中不是一个关键字,只是一个内置的变量,bool类型,值为1,即True+True输出2.
而且还可以被赋值.比如赋值True = 2, 甚至可以赋值True = False.
所以while True的时候, 每次循环都要检查True的值, 对应指令LOAD_NAME.
这就是为什么while True比while 1慢了.
不过在python3中,True变成了关键字了.while 1和while True的指令相同,所以没有性能区别了.

再来看个小例子,先来一小段代码:

In[6]: def test(): 
...   x = 1 
...   if x < 3: 
...    return "yes" 
...   else: 
...    return "no"

代码执行后会输出:

In[7]: import dis 
In[8]: dis.dis(test) 
 2   0 LOAD_CONST    1 (1) 
    3 STORE_FAST    0 (x) 
 
 3   6 LOAD_FAST    0 (x) 
    9 LOAD_CONST    2 (3) 
    12 COMPARE_OP    0 (<) 
    15 POP_JUMP_IF_FALSE  22 
 
 4   18 LOAD_CONST    3 ('yes') 
    21 RETURN_VALUE   
 
 6  >> 22 LOAD_CONST    4 ('no') 
    25 RETURN_VALUE   
    26 LOAD_CONST    0 (None) 
    29 RETURN_VALUE
以第一条指令为例, 第一列的数字(2)表示对应源代码的行数。第二列的数字是字节码的索引,指令LOAD_CONST在0位置。第三列是指令本身对应的人类可读的名字。第四列表示指令的参数。第5列则是计算后的实际参数。其中的“>>" 表示跳转的目标, 第4列的“22” 表明了跳转到索引为22的指令。Python代码在编译过程中会生成CodeObject, CodeObject是在虚拟机中的抽象表示, 在Python C源码中表示为PyCodeObject, 而生成的.pyc 文件则是字节码在磁盘中的表现形式。
以Python代码为讲,test.__code__.co_code 表示test函数的字节码指令序列。
将此序列打印出来,
code = [ord(i) for i in list(test.__code__.co_code)] 
print code

输出:

[100, 1, 0, 125, 0, 0, 124, 0, 0, 100, 2, 0, 107, 0, 0, 114, 22, 0, 100, 3, 0, 83, 100, 4, 0, 83, 100, 0, 0, 83] 

对照dis输出的字节码指令, 以[100,1,0]序列为例。100表示在Python字节码定义中的索引,在python代码中,
 可以通过dis.opname[100]查看,即为LOAD_CONST。而后的两个字节表示指令的参数。而dis输出的字节码指令中,
第二列的字节码索引则是指当前指令在co_code序列中所在的位置。
dis输出的字节码指令中,部分指令是没有参数, 在co_code 中也同样可以看到,83(RETURN_VALUE)直接接上下一条指令100(LOAD_CONST)。

Python 相关文章推荐
轻松掌握python设计模式之策略模式
Nov 18 Python
Python实现统计文本文件字数的方法
May 05 Python
浅谈Python里面小数点精度的控制
Jul 16 Python
Linux下多个Python版本安装教程
Aug 15 Python
python中的json总结
Oct 11 Python
将pandas.dataframe的数据写入到文件中的方法
Dec 07 Python
python 列表输出重复值以及对应的角标方法
Jun 11 Python
python 实现二维字典的键值合并等函数
Dec 06 Python
如何基于Python实现电子邮件的发送
Dec 16 Python
Python3 ID3决策树判断申请贷款是否成功的实现代码
May 21 Python
通过Python pyecharts输出保存图片代码实例
Nov 25 Python
matplotlib之pyplot模块之标题(title()和suptitle())
Feb 22 Python
Python的Flask框架中使用Flask-Migrate扩展迁移数据库的教程
Jun 14 #Python
Python的Flask框架中使用Flask-SQLAlchemy管理数据库的教程
Jun 14 #Python
全面了解Python的getattr(),setattr(),delattr(),hasattr()
Jun 14 #Python
浅谈python中的getattr函数 hasattr函数
Jun 14 #Python
深入解析Python中的线程同步方法
Jun 14 #Python
详解Python中的Descriptor描述符类
Jun 14 #Python
浅析Python中的getattr(),setattr(),delattr(),hasattr()
Jun 14 #Python
You might like
在DC的漫画和电影中,蝙蝠侠的宿敌,小丑的真名是什么?
2020/04/09 欧美动漫
PHP文本数据库的搜索方法
2006/10/09 PHP
PHP的FTP学习(一)
2006/10/09 PHP
ThinkPHP实例化模型的四种方法概述
2014/08/22 PHP
PHP封装的Twitter访问类实例
2015/07/18 PHP
php HTML无刷新提交表单
2016/04/05 PHP
ThinkPHP中create()方法自动验证表单信息
2017/04/28 PHP
PHP单例模式实例分析【防继承,防克隆操作】
2019/05/22 PHP
javascript 全等号运算符使用说明
2010/05/31 Javascript
JQuery动态给table添加、删除行 改进版
2011/01/19 Javascript
Json字符串转换为JS对象的高效方法实例
2013/05/01 Javascript
jQuery中andSelf()方法用法实例
2015/01/08 Javascript
jQuery模拟新浪微博首页滚动效果的方法
2015/03/11 Javascript
jQuery仿gmail实现fixed布局的方法
2015/05/27 Javascript
jQuery插件EnPlaceholder实现输入框提示文字
2015/06/05 Javascript
gulp-htmlmin压缩html的gulp插件实例代码
2016/06/06 Javascript
jQuery简单注册和禁用全局事件的方法
2016/07/25 Javascript
有关文件上传 非ajax提交 得到后台数据问题
2016/10/12 Javascript
Angularjs使用指令做表单校验的方法
2017/03/31 Javascript
Kotlin学习第一步 kotlin语法特性
2017/05/25 Javascript
详解Vue整合axios的实例代码
2017/06/21 Javascript
jQuery实现拖动效果的实例代码
2017/06/25 jQuery
浅谈Webpack 持久化缓存实践
2018/03/22 Javascript
jQuery插件Validation表单验证详解
2018/05/26 jQuery
Vue-Router的使用方法
2018/09/05 Javascript
js操作table中tr的顺序实现上移下移一行的效果
2018/11/22 Javascript
原生JS实现的跳一跳小游戏完整实例
2019/01/27 Javascript
python爬取m3u8连接的视频
2018/02/28 Python
python 实现语音聊天机器人的示例代码
2018/12/02 Python
详解pandas.DataFrame中删除包涵特定字符串所在的行
2019/04/04 Python
Django admin model 汉化显示文字的实现方法
2019/08/12 Python
使用OpenCV实现仿射变换—旋转功能
2019/08/29 Python
2015年志愿者服务工作总结
2015/04/20 职场文书
2015年小学校长工作总结
2015/05/19 职场文书
python绘图subplots函数使用模板的示例代码
2021/04/30 Python
「月刊Comic Alive」2022年5月号封面公开
2022/03/21 日漫