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程序与MySQL的教程
Apr 29 Python
python实现爬虫统计学校BBS男女比例(一)
Dec 31 Python
Python发送http请求解析返回json的实例
Mar 26 Python
Python实现的knn算法示例
Jun 14 Python
解决tensorflow测试模型时NotFoundError错误的问题
Jul 27 Python
在Python中定义一个常量的方法
Nov 10 Python
python感知机实现代码
Jan 18 Python
在Python 中同一个类两个函数间变量的调用方法
Jan 31 Python
django rest framework 实现用户登录认证详解
Jul 29 Python
Python3.6+selenium2.53.6自动化测试_读取excel文件的方法
Sep 06 Python
基于python的selenium两种文件上传操作实现详解
Sep 19 Python
Visual Studio code 配置Python开发环境
Sep 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
Protoss兵种介绍
2020/03/14 星际争霸
php自定义函数实现二维数组按指定key排序的方法
2016/09/29 PHP
php实现的中秋博饼游戏之掷骰子并输出结果功能详解
2017/11/06 PHP
javascript下function声明一些小结
2007/12/28 Javascript
js常用代码段收集
2011/10/28 Javascript
js获取元素外链样式的方法
2015/01/27 Javascript
JavaScript中数组继承的简单示例
2015/07/29 Javascript
JavaScrip常见的一些算法总结
2015/12/28 Javascript
jquery轮播的实现方式 附完整实例
2016/07/28 Javascript
JS判断指定dom元素是否在屏幕内的方法实例
2017/01/23 Javascript
jQuery插件FusionWidgets实现的Cylinder图效果示例【附demo源码】
2017/03/23 jQuery
Angular.JS中指令ng-if的注意事项小结
2017/06/21 Javascript
Vue.js分页组件实现:diVuePagination的使用详解
2018/01/10 Javascript
微信小程序实现动态显示和隐藏某个控件功能示例
2018/12/14 Javascript
使用vue实现一个电子签名组件的示例代码
2020/01/06 Javascript
jQuery实现小火箭返回顶部特效
2020/02/03 jQuery
JavaScript实现轮播图特效
2020/04/10 Javascript
[02:12]DOTA2英雄基础教程 变体精灵
2013/12/16 DOTA
[02:24]DOTA2亚洲邀请赛 NAVI战队出场宣传片
2015/02/07 DOTA
Python模拟登录12306的方法
2014/12/30 Python
python将秒数转化为时间格式的实例
2018/09/16 Python
Django通过dwebsocket实现websocket的例子
2019/11/15 Python
基于torch.where和布尔索引的速度比较
2020/01/02 Python
python 计算方位角实例(根据两点的坐标计算)
2020/01/17 Python
Python中私有属性的定义方式
2020/03/05 Python
基于css3的属性transition制作菜单导航效果
2015/09/01 HTML / CSS
CSS3 rgb and rgba(透明色)的使用详解
2020/09/25 HTML / CSS
MANGO官方网站:西班牙芒果服装品牌
2017/01/15 全球购物
企业年度评优方案
2014/06/02 职场文书
总经理人事任命书
2014/06/05 职场文书
防汛工作情况汇报
2014/10/28 职场文书
城南旧事读书笔记
2015/06/29 职场文书
python制作图形界面的2048游戏, 基于tkinter
2021/04/06 Python
Python答题卡识别并给出分数的实现代码
2021/06/22 Python
Golang入门之计时器
2022/05/04 Golang
MySQL中的 inner join 和 left join的区别解析(小结果集驱动大结果集)
2023/05/08 MySQL