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中关键字is与==的区别简述
Jul 31 Python
Python中解析JSON并同时进行自定义编码处理实例
Feb 08 Python
Python编程入门之Hello World的三种实现方式
Nov 13 Python
5种Python单例模式的实现方式
Jan 14 Python
Python正则表达式经典入门教程
May 22 Python
numpy matrix和array的乘和加实例
Jun 28 Python
python基于递归解决背包问题详解
Jul 03 Python
Python使用random模块生成随机数操作实例详解
Sep 17 Python
简单介绍django提供的加密算法
Dec 18 Python
利用python生成照片墙的示例代码
Apr 09 Python
python中pivot()函数基础知识点
Jan 03 Python
详解python的异常捕获
Mar 03 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初学者的8点有效建议
2010/11/20 PHP
YII视图整合kindeditor扩展的方法
2016/07/13 PHP
基于PHP+mysql实现新闻发布系统的开发
2020/08/06 PHP
Firefox+FireBug使JQuery的学习更加轻松愉快
2010/01/01 Javascript
一个简单的js动画效果代码
2010/07/20 Javascript
Document对象内容集合(比较全)
2010/09/06 Javascript
jquery+css3打造一款ajax分页插件(自写)
2014/06/18 Javascript
wap图片滚动特效无css3元素纯js脚本编写
2014/08/22 Javascript
jQuery搜索同辈元素方法
2015/02/10 Javascript
js实现a标签超链接提交form表单的方法
2015/06/24 Javascript
jQuery插件pagewalkthrough实现引导页效果
2015/07/05 Javascript
JavaScript中最容易混淆的作用域、提升、闭包知识详解(推荐)
2016/09/05 Javascript
javascript实现秒表计时器的制作方法
2017/02/16 Javascript
基于vue.js中事件修饰符.self的用法(详解)
2018/02/23 Javascript
vue cli webpack中使用sass的方法
2018/02/24 Javascript
vue-cli3全面配置详解
2018/11/14 Javascript
Layui选项卡制作历史浏览记录的方法
2019/09/28 Javascript
vue页面加载时的进度条功能(实例代码)
2020/01/13 Javascript
Javascript中的奇葩知识,你知道吗?
2021/01/25 Javascript
[03:37]2015国际邀请赛第四日现场精彩集锦
2015/08/08 DOTA
[01:08:43]DOTA2-DPC中国联赛定级赛 Phoenix vs DLG BO3第一场 1月9日
2021/03/11 DOTA
python元组操作实例解析
2014/09/23 Python
python在不同条件下的输入与输出
2020/02/13 Python
在python3中实现更新界面
2020/02/21 Python
浅谈python 调用open()打开文件时路径出错的原因
2020/06/05 Python
tensorflow与numpy的版本兼容性问题的解决
2021/01/08 Python
美国电子元器件分销商:Newark element14
2018/01/13 全球购物
法国在线药房:Shop Pharmacie
2019/11/26 全球购物
招商业务员岗位职责
2013/12/16 职场文书
小学语文教学反思
2014/02/10 职场文书
洗车工岗位职责
2014/03/15 职场文书
纪检干部对照检查材料
2014/08/22 职场文书
党员干部批评与自我批评反四风思想汇报
2014/09/21 职场文书
2014年终个人工作总结
2014/11/07 职场文书
2015幼儿园新学期寄语
2015/02/27 职场文书
详解Apache SkyWalking 告警配置指南
2021/04/22 Servers