[oeasy]python0010 - python虚拟机解释执行py文件的原理

oeasy -
[oeasy]python0010 - python虚拟机解释执行py文件的原理
解释运行程序 🥊回忆上次内容

我们这次设置了断点

设置断点的目的是更快地调试调试的目的是去除 bug别害怕 bug一步步地总能找到 bug

这就是程序员基本功

调试 debug

我心中还是有疑问

python3 是怎么解释 hello.py 的?🤔纯文本我们的py文件是一个纯文本文件

图片描述

打开我们的guido.py

如果没有就新做一个这里面是一个个的字符
print("1982------Guido in cwi")
print("1995------Guido in cnri")
print("2000------Guido in beopen")
print("2005------Guido in google")
print("2012------Guido in dropbox")
print("2020------Guido in microsoft")
python怎知道如何执行呢?传统文本传统文本的基础也是字符

图片描述

在字符的基础上组织起篇章结构

字组成词词组成句句组成段段组成章节最后成书tokenize首先把一个个字符组成词

分析一下哪些字可以组成词

术语叫词法分析(lexical analysis)

图片描述

把原来的字符流

变成了词的流token(令牌)流

图片描述

词法分析之后输出的是一个词(token)的流

啥是token呢?token

token

令牌

图片描述

古人说听我号令

号指的是

号角摔杯为号是一个信号

令指的是令牌

急急如律令打五十大板令行禁止怎么把源文件变成一个词(token)流呢?python3模块帮助手册里面有这个内容这个tokenize是python3的一个模块(module)

图片描述

具体怎么运行呢?token流

图片描述

我们尝试运行

python3 -m tokenize guido.py

-m 代表的是 module模块对guido.py进行词法分析分析出来的词(token)流什么样子呢?这个词的流怎么理解呢?token流第0行设置了编码格式

第1行[0,5)字符是第1行第1个token

printprint是一个Name(名字)

第1行[5,6)字符是第1行第2个token

((是一个Operator(操作符)

第1行[6,30)字符是第1行第3个token

"1982------Guido in cwi"这是一个String(字符串)

第1行[30,31)字符是第1行第4个token

))是一个Operator(操作符)

第1行[31,32)字符是第1行第5个token

\n\n是一个NewLine(换行符)换行符意味着第一行结束

图片描述

第2行...词分析出来之后呢?组词

词分析出来就是怎么组词的问题

哪些词和哪些词先组合哪些词和哪些词后组合

生成一棵抽象语法树

AST(Abstract Syntax Tree)

图片描述

我能看看这棵ast树么?引入ast模块

图片描述

具体怎么做呢?流程

先把这个ast模块导入(import)进来

第一句就是import ast回车之后没有任何报错那就是执行成功了后面也一样没有报错就是执行成功了

图片描述

然后读取guido.py并送到s然后对于s进行语法分析(parse)

图片描述

再把分析(parse)的结果进行转储(dump)

看起来有点乱

可以清晰一些么?升级Python目前lanqiao.cn上面的python是3.8这个清晰缩进的格式需要在3.9以上完成需要升级
sudo apt update
sudo apt install python3.9
升级之后就可以使用Python3.9了

图片描述

缩进换行只能在本地演示一下

图片描述

这个就是把词组成语法树的样子如何理解这棵树呢?我们看一个例子表达式运算如果给的表达式为 1 2 3

图片描述

结合序为下图

图片描述

前两个先结合得到的结果作为下一个运算的左操作数然后和第3个结合结合序如果把 第一个* 改成 + 号其他什么也没加

图片描述

表达式是1 + 2 * 3

图片描述

后两个会先结合得到的结果作为下一个运算的右操作数然后再和1进行加法运算

有了语法树

下一步要做什么呢?这棵语法树我们能看懂但是cpu需要的是能执行的一条条字节码指令翻译成字节码

要把源程序翻译成字节码才能执行

字节码对应着cpu的指令

怎么把ast转化为字节码(指令)呢?

需要编译(compile)

从一种语言到另一种语言

从py文件到字节码(指令)就是编译

图片描述

我可以看看这个编译过程么?compile

图片描述

编译结果

编译(compile)之后得到是字节码指令文件

所以扩展名是pyc其中c代表compiledpyc是字节码(bytecode)文件python虚拟机的虚拟cpu就可以直接执行了

图片描述

先看看这个pyc文件

注意他在__pycache__文件夹下cache的意思是缓存pycache两端各有2条下划线(_)

图片描述

进这个文件夹看看进入__pycache__文件夹打开pyc文件

图片描述

得到的字节码看起来完全是乱码

可以想办法看懂这些字节码么?vi打开这个这个pyc文件二进制形态:set wrap设置换行

图片描述

这样看到了他的字符串形态可以看到他的二进制字节形态么?机器语言

:%!xxd

把文件转化为字节形态

图片描述

这纯纯的机器语言字节形态

实在是看不懂啊😭这真的是指令么?究竟什么是指令呢?指令instruction

图片描述

最早指的是教的行为或者过程

计算机领域里面特指指令

比如加法指令减法指令可以让cpu做特定运算的指令

图片描述

由于计算机只认识0和1所以要把这些加加减减的指令对应到0和1的二进制形态上去0和1的二进制形态我们记不住于是有了汇编助记符助记符告诉我们这条0和1的二进制形态到底对应什么指令助记符的语言就是汇编语言汇编assemble

图片描述

assemble指的是收集、集结

assembler指的是装卸工

在计算机中特指汇编语言

可以让我们把0和1的机器指令收集起来形成的助记符集合就是汇编语言指令集

图片描述

这就是汇编语言和0101的对应关系反编译disassemble

这个词由两部分组成

dis (反着来的)

dislikedisgracedisagree

assembler (汇编语言)

disassemble 反编译

把py源文件编译成的字节码(指令)我们人类看不明白

把这些字节码(指令)反编译(disassemble)成汇编语言助记符有了助记符我们就知道指令的含义了

图片描述

这可以用么?

去试试!反编译(dis)

python3 -m dis guido.py

-m 代表使用模块dis 代表反编译(disassemble)

图片描述

我们可以看见

前面是行号

每行对应4条指令

LOAD_NAME 装载(函数)名字LOAD_CONST 装载常量CALL_FUNCTION 调用函数POP_TOP 弹栈

总共6句

对应6组字节码每组两个字节那具体这个 LOAD_NAME 是要做些什么呢?指令

LOAD_NAME

把一个值压入堆栈co_names把print这个函数名压入了堆栈一会儿就要调用这个被压入堆栈的print函数

图片描述

但是LOAD_NAME这条指令

具体对应什么二进制字节状态呢?这个去哪里找呢?python源头python是从哪里来的呢?

图片描述

python 是开源编程语言整个的源代码都是开放的

我们可以去github找到他的源代码

https://github.com/python/cpy...二进制状态

搜索LOAD_NAME并且排查

找到字节码状态位置

指令对应着一个字节码状态值

https://github.com/python/cpy...

图片描述

这样我们能否找到4条指令分别对应的字节状态值4条指令指令助记符指令含义十进制状态十六进制状态LOAD_NAME装载函数名称1010x65LOAD_CONST装载参数1000x64CALL_FUNCTION调用函数1420x8ePOP_TOP弹栈返回10x01可以找到源代码的对应关系么?

图片描述

好像找到了

64XX

64 00是从表中的00号位置取得字符串"Guido in cwi"64 01是从表中的01号位置取字符串"Guido in cnri"...以此类推,直到05 83取出字符串"Guido in microsoft"

0x83 对应的是 GET_AWAITABLE

可等待地调用那这些二进制代码究竟是什么指令集的呢?首先我们得弄懂什么是指令集呢?指令集

指令集 就是

指令的集合

图片描述

上图是arm的指令集也常被称作arm架构那什么又是架构呢?architect

architect原本的英文含义是

建筑

图片描述

architecture

造房子的人就是建筑师

图片描述

在cpu领域

architectarchitecture指的是什么呢?架构师

图片描述

架构师

软件开发行业从业者的终极形态非常硬核的存在

图片描述

那python的字节码用的是什么架构呢?

arm还是x86呢?虚拟机的虚拟cpu

pyc的这些字节码(bytecode)

对应的是python虚拟机上面虚拟cpu的指令集

图片描述

cpu也能虚拟吗?

我们先把这节课总结一下总结

我们把python源文件

词法分析 得到 词流(token stream)语法分析 得到 抽象语法树(Abstract Syntax Tree)编译 得到 字节码 (bytecode)字节码我们看不懂所以反编译 得到 指令文件(opcode)

图片描述

指令文件是基于python虚拟机的虚拟cpu的指令集什么是python虚拟机呢?🤔我们下次再说👋蓝桥->https://www.lanqiao.cn/teache...github->https://github.com/overmind19...gitee->https://gitee.com/overmind198...视频->https://www.bilibili.com/vide... 作者:oeasy
特别申明:本文内容来源网络,版权归原作者所有,如有侵权请立即与我们联系(cy198701067573@163.com),我们将及时处理。

Tags 标签

python虚拟机linuxlex

扩展阅读

加个好友,技术交流

1628738909466805.jpg