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 相关文章推荐
Cython 三分钟入门教程
Sep 17 Python
Python中的startswith和endswith函数使用实例
Aug 25 Python
Python实现Const详解
Jan 27 Python
使用Python实现一个简单的项目监控
Mar 31 Python
Python访问纯真IP数据库脚本分享
Jun 29 Python
python正则分析nginx的访问日志
Jan 17 Python
python版本的仿windows计划任务工具
Apr 30 Python
浅谈keras中loss与val_loss的关系
Jun 22 Python
Python如何在单元测试中给对象打补丁
Aug 03 Python
python em算法的实现
Oct 03 Python
Matplotlib animation模块实现动态图
Feb 25 Python
用Python实现屏幕截图详解
Jan 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
Windows下IIS6/Apache2.2.4+MySQL5.2+PHP5.2.1安装配置方法
2007/05/03 PHP
PHP正确配置mysql(apache环境)
2011/08/28 PHP
destoon在各个服务器下设置URL Rewrite(伪静态)的方法
2014/06/21 Servers
PHP结合Mysql数据库实现留言板功能
2016/03/04 PHP
通过JAVASCRIPT读取ASP设定的COOKIE
2006/11/24 Javascript
JavaScript 存在陷阱 删除某一区域所有节点
2010/05/10 Javascript
js escape,unescape解决中文乱码问题的方法
2010/05/26 Javascript
jQuery回车实现登录简单实现
2013/08/20 Javascript
js动态设置div的值下例子
2013/10/29 Javascript
jQuery学习笔记之jQuery原型属性和方法
2014/06/09 Javascript
chrome浏览器当表单自动填充时如何去除浏览器自动添加的默认样式
2015/10/09 Javascript
js和C# 时间日期格式转换的简单实例
2016/05/28 Javascript
JavaScript基础之AJAX简单的小demo
2017/01/29 Javascript
js实现兼容PC端和移动端滑块拖动选择数字效果
2017/02/16 Javascript
解决npm安装Electron缓慢网络超时导致失败的问题
2018/02/06 Javascript
Angular异步变同步处理方法
2018/08/13 Javascript
vuex提交state&amp;&amp;实时监听state数据的改变方法
2018/09/16 Javascript
详解BootStrap表单验证中重置BootStrap-select验证提示不清除的坑
2019/09/17 Javascript
[39:53]完美世界DOTA2联赛PWL S2 LBZS vs Forest 第一场 11.19
2020/11/19 DOTA
python3模拟百度登录并实现百度贴吧签到示例分享(百度贴吧自动签到)
2014/02/24 Python
在Python程序中进行文件读取和写入操作的教程
2015/04/28 Python
Python实现字典的key和values的交换
2015/08/04 Python
python3利用Dlib19.7实现人脸68个特征点标定
2018/02/26 Python
详解python 模拟豆瓣登录(豆瓣6.0)
2019/04/18 Python
python定义类self用法实例解析
2020/01/22 Python
python3+opencv 使用灰度直方图来判断图片的亮暗操作
2020/06/02 Python
Python-openCV开运算实例
2020/07/05 Python
Python scrapy爬取小说代码案例详解
2020/07/09 Python
分布式数据库需要考虑哪些问题
2013/12/08 面试题
市政施工员自我鉴定
2014/01/15 职场文书
安全事故检讨书
2014/01/18 职场文书
孝敬父母的演讲稿
2014/05/14 职场文书
2014年乡镇领导个人整改措施
2014/09/19 职场文书
2016新年问候语大全
2015/11/11 职场文书
如何设计高效合理的MySQL查询语句
2021/05/26 MySQL
进行数据处理的6个 Python 代码块分享
2022/04/06 Python