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使用rsa加密算法模块模拟新浪微博登录
Jan 22 Python
python中enumerate的用法实例解析
Aug 18 Python
Python3 socket同步通信简单示例
Jun 07 Python
Python日期时间模块datetime详解与Python 日期时间的比较,计算实例代码
Sep 14 Python
Python实现打砖块小游戏代码实例
May 18 Python
Django 实现前端图片压缩功能的方法
Aug 07 Python
redis数据库及与python交互用法简单示例
Nov 01 Python
Python 装饰器原理、定义与用法详解
Dec 07 Python
python可视化text()函数使用详解
Feb 11 Python
Python 多线程共享变量的实现示例
Apr 17 Python
教你用python实现12306余票查询
Jun 30 Python
Python中的变量与常量
Nov 11 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判断网页是否gzip压缩
2013/06/25 PHP
php实现的九九乘法口诀表简洁版
2014/07/28 PHP
PHP两种快速排序算法实例
2015/02/15 PHP
php实现的mongodb操作类实例
2015/04/03 PHP
PHP实现json_decode不转义中文的方法
2017/05/20 PHP
基于JavaScript自定义构造函数的详解说明
2013/04/24 Javascript
浅谈javascript对象模型和function对象
2014/12/26 Javascript
setinterval()与clearInterval()JS函数的调用方法
2015/01/21 Javascript
JavaScript实现按照指定长度为数字前面补零输出的方法
2015/03/19 Javascript
JavaScript生成福利彩票双色球号码
2015/05/15 Javascript
JavaScript中字符串(string)转json的2种方法
2015/06/25 Javascript
IE8下jQuery改变png图片透明度时出现的黑边
2015/08/30 Javascript
package.json文件配置详解
2017/06/15 Javascript
原生JavaScript实现Ajax异步请求
2017/11/19 Javascript
详解JavaScript对数组操作(添加/删除/截取/排序/倒序)
2019/04/28 Javascript
JS中的算法与数据结构之队列(Queue)实例详解
2019/08/20 Javascript
webpack安装配置与常见使用过程详解(结合vue)
2020/06/01 Javascript
vue实现简单图片上传
2020/06/30 Javascript
[03:09]显微镜下的DOTA2第一期——带你走进华丽的DOTA2世界
2014/06/20 DOTA
基于Python代码编辑器的选用(详解)
2017/09/13 Python
python3利用ctypes传入一个字符串类型的列表方法
2019/02/12 Python
GitHub 热门:Python 算法大全,Star 超过 2 万
2019/04/29 Python
浅析Python3 pip换源问题
2020/01/06 Python
Python ArgumentParse的subparser用法说明
2020/04/20 Python
GUESS德国官网:美国牛仔服装品牌
2017/02/14 全球购物
心理健康心得体会
2014/01/02 职场文书
致跳远、跳高运动员广播稿
2014/01/09 职场文书
2014年基层党组织公开承诺书
2014/03/29 职场文书
八一建军节营销活动方案
2014/08/31 职场文书
婚庆公司计划书
2014/09/15 职场文书
招标授权委托书样本
2014/09/23 职场文书
2014年语文教研组工作总结
2014/12/06 职场文书
2015年清明节演讲稿范文
2015/03/17 职场文书
2015年七七事变78周年纪念活动方案
2015/05/06 职场文书
2015年检察院个人工作总结
2015/05/20 职场文书
python自动化八大定位元素讲解
2021/07/09 Python