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】Python的urllib模块、urllib2模块批量进行网页下载文件
Nov 19 Python
Python实现OpenCV的安装与使用示例
Mar 30 Python
Python爬虫PyQuery库基本用法入门教程
Aug 04 Python
pycharm无法导入本地模块的解决方式
Feb 12 Python
python下载卫星云图合成gif的方法示例
Feb 18 Python
Python爬取365好书中小说代码实例
Feb 28 Python
tensorflow常用函数API介绍
Apr 19 Python
Pytho爬虫中Requests设置请求头Headers的方法
Sep 22 Python
Python通过format函数格式化显示值
Oct 17 Python
Python word文本自动化操作实现方法解析
Nov 05 Python
python中的unittest框架实例详解
Feb 05 Python
Autopep8的使用(python自动编排工具)
Mar 02 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面向对象概念
2011/11/06 PHP
PHP计数器的实现代码
2013/06/08 PHP
PHP使用SOAP调用.net的WebService数据
2013/11/12 PHP
PHP自毁程序(慎用)
2015/07/09 PHP
PHP环境中Memcache的安装和使用
2015/11/05 PHP
Javascript &amp; DHTML 实例编程(教程)DOM基础和基本API
2007/06/02 Javascript
js 异步操作回调函数如何控制执行顺序
2013/12/24 Javascript
JS中的log对象获取以及debug的写法介绍
2014/03/03 Javascript
JS替换字符串中字符即替换全部而不是第一个
2014/06/04 Javascript
jquery向上向下取整适合分页查询
2014/09/06 Javascript
谈谈AngularJs中的隐藏和显示
2015/12/09 Javascript
jQuery实现下拉框功能实例代码
2016/05/06 Javascript
jquery延迟对象解析
2016/10/26 Javascript
vue+elementui 对话框取消 表单验证重置示例
2019/10/29 Javascript
用jQuery实现抽奖程序
2020/04/12 jQuery
vue-cli4使用全局less文件中的变量配置操作
2020/10/21 Javascript
[57:55]完美世界DOTA2联赛PWL S3 Magma vs Phoenix 第二场 12.12
2020/12/16 DOTA
Python解析json之ValueError: Expecting property name enclosed in double quotes: line 1 column 2(char 1)
2017/07/06 Python
Python入门之三角函数tan()函数实例详解
2017/11/08 Python
使用apidocJs快速生成在线文档的实例讲解
2018/02/07 Python
python 借助numpy保存数据为csv格式的实现方法
2018/07/04 Python
python 实现UTC时间加减的方法
2018/12/31 Python
对python中 math模块下 atan 和 atan2的区别详解
2020/01/17 Python
解决Jupyter Notebook开始菜单栏Anaconda下消失的问题
2020/04/13 Python
味多美官网:蛋糕订购,100%使用天然奶油
2017/11/10 全球购物
给老婆的婚前保证书
2014/02/01 职场文书
幼儿教师师德演讲稿
2014/05/06 职场文书
职员竞岗演讲稿
2014/05/14 职场文书
厉行勤俭节约倡议书
2014/05/16 职场文书
信息合作协议书
2014/10/09 职场文书
大学生毕业评语
2014/12/31 职场文书
个人工作年终总结
2015/03/09 职场文书
请客吃饭开场白
2015/06/01 职场文书
入党培养人考察意见
2015/06/08 职场文书
公开致歉信
2019/06/24 职场文书
Redis配置外网可访问(redis远程连接不上)的方法
2022/12/24 Redis