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正则表达式操作指南(re使用)
Sep 06 Python
基于Python中求和函数sum的用法详解
Jun 28 Python
Python sorted函数详解(高级篇)
Sep 18 Python
解决pyinstaller打包pyqt5的问题
Jan 08 Python
Pyqt5如何让QMessageBox按钮显示中文示例代码
Apr 11 Python
使用python制作一个为hex文件增加版本号的脚本实例
Jun 12 Python
Django用户认证系统 User对象解析
Aug 02 Python
利用Python计算KS的实例详解
Mar 03 Python
Python序列化pickle模块使用详解
Mar 05 Python
Python迭代器协议及for循环工作机制详解
Jul 14 Python
Python 中如何写注释
Aug 28 Python
python manim实现排序算法动画示例
Aug 14 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
让的PHP代码飞起来的40条小技巧(提升php效率)
2010/04/12 PHP
php 中英文语言转换类代码
2011/08/11 PHP
php curl常见错误:SSL错误、bool(false)
2011/12/28 PHP
详解PHP的Yii框架的运行机制及其路由功能
2016/03/17 PHP
php curl简单采集图片生成base64编码(并附curl函数参数说明)
2019/02/15 PHP
js静态作用域的功能。
2006/12/25 Javascript
得到文本框选中的文字,动态插入文字的js代码
2007/03/07 Javascript
WordPress中利用AJAX技术进行评论提交的实现示例
2016/01/12 Javascript
jquery validate表单验证的基本用法入门
2016/01/18 Javascript
JavaScript中instanceof运算符的使用示例
2016/06/08 Javascript
通过BootStrap-select插件 js jQuery控制select属性变化
2017/01/03 Javascript
谈谈Vue.js——vue-resource全攻略
2017/01/16 Javascript
动态加载css方法实现和深入解析
2017/01/18 Javascript
vue-cli的webpack模板项目配置文件分析
2017/04/01 Javascript
jquery加载单文件vue组件的方法
2017/06/20 jQuery
JS实现加载时锁定HTML页面元素的方法
2017/06/24 Javascript
基于Vue2的独立构建与运行时构建的差别(详解)
2017/12/06 Javascript
vue组件的写法汇总
2018/04/12 Javascript
Nodejs实现爬虫抓取数据实例解析
2018/07/05 NodeJs
JavaScript模板引擎原理与用法详解
2018/12/24 Javascript
Vuejs通过拖动改变元素宽度实现自适应
2020/09/02 Javascript
Python实现Youku视频批量下载功能
2017/03/14 Python
基于python实现把图片转换成素描
2019/11/13 Python
Python 读取WAV音频文件 画频谱的实例
2020/03/14 Python
在tensorflow以及keras安装目录查询操作(windows下)
2020/06/19 Python
Python获取浏览器窗口句柄过程解析
2020/07/25 Python
澳大利亚儿童精品仓库:Goo & Co.
2019/06/20 全球购物
六道php面试题附答案
2014/06/05 面试题
天逸系统(武汉)有限公司Java笔试题
2015/12/29 面试题
存储过程的优缺点是什么
2015/01/10 面试题
网络维护管理员的自我评价分享
2013/11/11 职场文书
社区包粽子活动方案
2014/01/21 职场文书
课改先进个人汇报材料
2014/01/26 职场文书
行政副总岗位职责
2014/02/23 职场文书
学生个人自我鉴定范文
2014/03/28 职场文书
幼儿园六一亲子活动方案
2014/08/26 职场文书