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 while、for、生成器、列表推导等语句的执行效率测试
Jun 03 Python
Python中强大的命令行库click入门教程
Dec 26 Python
使用Python对SQLite数据库操作
Apr 06 Python
用Python写脚本,实现完全备份和增量备份的示例
Apr 29 Python
python引入不同文件夹下的自定义模块方法
Oct 27 Python
python 中Arduino串口传输数据到电脑并保存至excel表格
Oct 14 Python
pytorch 获取tensor维度信息示例
Jan 03 Python
Python统计学一数据的概括性度量详解
Mar 03 Python
通过代码实例了解Python3编程技巧
Oct 13 Python
python3代码中实现加法重载的实例
Dec 03 Python
Python实现文字pdf转换图片pdf效果
Apr 03 Python
使用Python通过企业微信应用给企业成员发消息
Apr 18 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返回相对时间(如:20分钟前,3天前)的方法
2015/04/14 PHP
使用php-timeit估计php函数的执行时间
2015/09/06 PHP
laravel学习教程之存取器
2016/07/30 PHP
php实现姓名根据首字母排序的类与方法(实例代码)
2018/05/16 PHP
PHP之header函数详解
2021/03/02 PHP
通过event对象的fromElement属性解决热区设置主实体的一个bug
2008/12/22 Javascript
简洁短小的 JavaScript IE 浏览器判定代码
2010/03/21 Javascript
Javascript实现CheckBox的全选与取消全选的代码
2010/07/20 Javascript
(jQuery,mootools,dojo)使用适合自己的编程别名命名
2010/09/14 Javascript
jQuery实现随意改变div任意属性的名称和值(部分原生js实现)
2013/05/28 Javascript
jQuery.extend()、jQuery.fn.extend()扩展方法示例详解
2014/05/08 Javascript
js实现表单多按钮提交action的处理方法
2015/10/24 Javascript
JS操作JSON方法总结(推荐)
2016/06/14 Javascript
JavaScript实现点击文本自动定位到下拉框选中操作
2016/06/15 Javascript
javascript中数组(Array)对象和字符串(String)对象的常用方法总结
2016/12/15 Javascript
Vue中父组件向子组件通信的方法
2017/07/11 Javascript
javaScript canvas实现(画笔大小 颜色 橡皮的实例)
2017/11/28 Javascript
JavaScript创建对象方法实例小结
2018/09/03 Javascript
微信小程序实现拖拽功能
2019/09/26 Javascript
vue实现分页加载效果
2019/12/24 Javascript
js获取url页面id,也就是最后的数字文件名
2020/09/25 Javascript
在Python程序中操作文件之isatty()方法的使用教程
2015/05/24 Python
Python切片索引用法示例
2018/05/15 Python
如何用Python制作微信好友个性签名词云图
2019/06/28 Python
Python3 批量扫描端口的例子
2019/07/25 Python
python 操作hive pyhs2方式
2019/12/21 Python
pytorch数据预处理错误的解决
2020/02/20 Python
Python类及获取对象属性方法解析
2020/06/15 Python
捷克家电和家具购物网站:OKAY.cz
2020/07/23 全球购物
职业技术学校毕业生推荐信
2013/12/03 职场文书
预备党员思想汇报
2014/01/08 职场文书
科技开发中心办公室主任岗位责任制
2014/02/10 职场文书
公司大门门卫岗位职责
2014/06/11 职场文书
2014年初一班主任工作总结
2014/11/08 职场文书
Python实现提取PDF简历信息并存入Excel
2022/04/02 Python
基于CSS制作创意端午节专属加载特效
2022/06/01 HTML / CSS