最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

[oeasy]python0010 - python虛擬機(jī)解釋執(zhí)行py文件的原理

2022-10-21 15:39 作者:oeasy  | 我要投稿

?

解釋運(yùn)行程序 ??


回憶上次內(nèi)容

  • 我們這次設(shè)置了斷點(diǎn)

  • 設(shè)置斷點(diǎn)的目的是更快地調(diào)試

  • 調(diào)試的目的是去除bug

  • 別害怕bug

  • 一步步地總能找到bug

  • 這就是程序員基本功

  • 調(diào)試debug

  • 我心中還是有疑問

  • python3 是怎么解釋hello.py 的???

純文本

  • 我們的 py 文件是一個(gè)純文本文件

  • 打開我們的 guido.py

  • 如果沒有就新做一個(gè)

  • 這里面是一個(gè)個(gè)的字符


  • python 怎知道如何執(zhí)行呢?

傳統(tǒng)文本

  • 傳統(tǒng)文本的基礎(chǔ)也是字符

  • 在字符的基礎(chǔ)上組織起篇章結(jié)構(gòu)

  • 字組成詞

  • 詞組成句

  • 句組成段

  • 段組成章節(jié)

  • 最后成書

tokenize

  • 首先把一個(gè)個(gè)字符組成詞

  • 分析一下哪些字可以組成詞

  • 術(shù)語叫詞法分析 (lexical analysis)

  • 把原來的字符流

  • 變成了詞的流

  • token (令牌) 流

  • 詞法分析之后輸出的是一個(gè)詞 (token) 的流

  • 啥是 token 呢?

token

  • token

  • 令牌

  • 古人說聽我號(hào)令

  • 號(hào)指的是

  • 號(hào)角

  • 摔杯為號(hào)

  • 是一個(gè)信號(hào)

  • 令指的是令牌

  • 急急如律令

  • 打五十大板

  • 令行禁止

  • 怎么把源文件變成一個(gè)詞 (token) 流呢?

python3 模塊

  • 幫助手冊(cè)里面有這個(gè)內(nèi)容

  • 這個(gè) tokenize 是 python3 的一個(gè)模塊 (module)

  • 具體怎么運(yùn)行呢?

token 流

  • 我們嘗試運(yùn)行

  • python3 -m tokenizeguido.py

  • -m 代表的是 module 模塊

  • 對(duì) guido.py 進(jìn)行詞法分析

  • 分析出來的詞 (token) 流什么樣子呢?

  • 這個(gè)詞的流怎么理解呢?

token 流

  • 第 0 行設(shè)置了編碼格式

  • 第 1 行 [0,5) 字符是第 1 行第 1 個(gè) token

  • print

  • print 是一個(gè) Name (名字)

  • 第 1 行 [5,6) 字符是第 1 行第 2 個(gè) token

  • (

  • (是一個(gè) Operator (操作符)

  • 第 1 行 [6,30) 字符是第 1 行第 3 個(gè) token

  • "1982------Guido in cwi"

  • 這是一個(gè) String (字符串)

  • 第 1 行 [30,31) 字符是第 1 行第 4 個(gè) token

  • )

  • ) 是一個(gè) Operator (操作符)

  • 第 1 行 [31,32) 字符是第 1 行第 5 個(gè) token

  • \n

  • \n 是一個(gè) NewLine (換行符)

  • 換行符意味著第一行結(jié)束

  • 第 2 行...

  • 詞分析出來之后呢?

組詞

  • 詞分析出來就是怎么組詞的問題

  • 哪些詞和哪些詞先組合

  • 哪些詞和哪些詞后組合

  • 生成一棵抽象語法樹

  • AST(Abstract Syntax Tree)

  • 我能看看這棵 ast 樹么?

引入 ast 模塊

  • 具體怎么做呢?

流程

  • 先把這個(gè) ast 模塊導(dǎo)入 (import) 進(jìn)來

  • 第一句就是 import ast

  • 回車之后沒有任何報(bào)錯(cuò)

  • 那就是執(zhí)行成功了

  • 后面也一樣

  • 沒有報(bào)錯(cuò)就是執(zhí)行成功了

  • 然后讀取 guido.py 并送到 s

  • 然后對(duì)于 s 進(jìn)行語法分析 (parse)

  • 再把分析 (parse) 的結(jié)果進(jìn)行轉(zhuǎn)儲(chǔ) (dump)

  • 看起來有點(diǎn)亂

  • 可以清晰一些么?

升級(jí) Python

  • 目前 lanqiao.cn 上面的 python 是 3.8

  • 這個(gè)清晰縮進(jìn)的格式需要在 3.9 以上完成

  • 需要升級(jí)

sudo apt updatesudo apt install python3.9

  • 升級(jí)之后就可以使用 Python3.9 了

縮進(jìn)換行

  • 只能在本地演示一下

  • 這個(gè)就是把詞組成語法樹的樣子

  • 如何理解這棵樹呢?

  • 我們看一個(gè)例子

表達(dá)式運(yùn)算

  • 如果給的表達(dá)式為 1 * 2 * 3

  • 結(jié)合序?yàn)橄聢D

  • 前兩個(gè)先結(jié)合

  • 得到的結(jié)果作為下一個(gè)運(yùn)算的左操作數(shù)

  • 然后和第 3 個(gè)結(jié)合

結(jié)合序

  • 如果把 第一個(gè) * 改成 + 號(hào)

  • 其他什么也沒加

  • 表達(dá)式是 1 + 2 * 3

  • 后兩個(gè)會(huì)先結(jié)合

  • 得到的結(jié)果作為下一個(gè)運(yùn)算的右操作數(shù)

  • 然后再和 1 進(jìn)行加法運(yùn)算

  • 有了語法樹

  • 下一步要做什么呢?

  • 這棵語法樹我們能看懂

  • 但是 cpu 需要的是能執(zhí)行的一條條字節(jié)碼指令

翻譯成字節(jié)碼

  • 要把源程序翻譯成字節(jié)碼才能執(zhí)行

  • 字節(jié)碼對(duì)應(yīng)著 cpu 的指令

  • 怎么把 ast 轉(zhuǎn)化為字節(jié)碼 (指令) 呢?

  • 需要編譯 (compile)

  • 從一種語言到另一種語言

  • 從 py 文件

  • 到字節(jié)碼 (指令)

  • 就是編譯

  • 我可以看看這個(gè)編譯過程么?

compile

編譯結(jié)果

  • 編譯 (compile) 之后得到是字節(jié)碼指令文件

  • 所以擴(kuò)展名是 pyc

  • 其中 c 代表 compiled

  • pyc 是字節(jié)碼 (bytecode) 文件

  • python 虛擬機(jī)的虛擬 cpu 就可以直接執(zhí)行了

  • 先看看這個(gè) pyc 文件

  • 注意他在__pycache__文件夾下

  • cache 的意思是緩存

  • pycache 兩端各有 2 條下劃線 (_)

  • 進(jìn)這個(gè)文件夾看看

進(jìn)入__pycache__文件夾

  • 打開 pyc 文件

  • 得到的字節(jié)碼看起來完全是亂碼

  • 可以想辦法看懂這些字節(jié)碼么?

  • vi 打開這個(gè)這個(gè) pyc 文件

二進(jìn)制形態(tài)

  • :set wrap 設(shè)置換行

  • 這樣看到了他的字符串形態(tài)

  • 可以看到他的二進(jìn)制字節(jié)形態(tài)么?

機(jī)器語言

  • :%!xxd

  • 把文件轉(zhuǎn)化為字節(jié)形態(tài)

  • 這純純的機(jī)器語言字節(jié)形態(tài)

  • 實(shí)在是看不懂啊??

  • 這真的是指令么?

  • 究竟什么是指令呢?

指令

  • instruction

  • 最早指的是教的行為或者過程

  • 計(jì)算機(jī)領(lǐng)域里面特指指令

  • 比如加法指令

  • 減法指令

  • 可以讓 cpu 做特定運(yùn)算的指令

  • 由于計(jì)算機(jī)只認(rèn)識(shí) 0 和 1

  • 所以要把這些加加減減的指令

  • 對(duì)應(yīng)到 0 和 1 的二進(jìn)制形態(tài)上去

  • 0 和 1 的二進(jìn)制形態(tài)我們記不住

  • 于是有了匯編助記符

  • 助記符告訴我們這條 0 和 1 的二進(jìn)制形態(tài)

  • 到底對(duì)應(yīng)什么指令

  • 助記符的語言就是匯編語言

匯編 assemble

  • assemble 指的是收集、集結(jié)

  • assembler 指的是裝卸工

  • 在計(jì)算機(jī)中特指匯編語言

  • 可以讓我們把 0 和 1 的機(jī)器指令

  • 收集起來形成的助記符集合

  • 就是匯編語言指令集

  • 這就是匯編語言和 0101 的對(duì)應(yīng)關(guān)系

反編譯

  • disassemble

  • 這個(gè)詞由兩部分組成

  • dis (反著來的)

?

  • dislike

  • disgrace

  • disagree

  • assembler (匯編語言)

  • disassemble 反編譯

  • 把 py 源文件編譯成的字節(jié)碼 (指令) 我們?nèi)祟惪床幻靼?/p>

  • 把這些字節(jié)碼 (指令) 反編譯 (disassemble) 成匯編語言助記符

  • 有了助記符我們就知道指令的含義了

  • 這可以用么?

  • 去試試!

反編譯 (dis)

  • python3 -m disguido.py

  • -m 代表使用模塊

  • dis 代表反編譯 (disassemble)

  • 我們可以看見

  • 前面是行號(hào)

  • 每行對(duì)應(yīng) 4 條指令

  • LOAD_NAME 裝載 (函數(shù)) 名字

  • LOAD_CONST 裝載常量

  • CALL_FUNCTION 調(diào)用函數(shù)

  • POP_TOP 彈棧

  • 總共 6 句

  • 對(duì)應(yīng) 6 組字節(jié)碼

  • 每組兩個(gè)字節(jié)

  • 那具體這個(gè) LOAD_NAME 是要做些什么呢?

指令

  • LOAD_NAME

  • 把一個(gè)值壓入堆棧 co_names

  • 把 print 這個(gè)函數(shù)名壓入了堆棧

  • 一會(huì)兒就要調(diào)用這個(gè)被壓入堆棧的 print 函數(shù)

  • 但是 LOAD_NAME 這條指令

  • 具體對(duì)應(yīng)什么二進(jìn)制字節(jié)狀態(tài)呢?

  • 這個(gè)去哪里找呢?

python 源頭

  • python 是從哪里來的呢?

  • python 是開源編程語言

  • 整個(gè)的源代碼都是開放的

  • 我們可以去 github 找到他的源代碼

  • https://github.com/python/cpython

二進(jìn)制狀態(tài)

  • 搜索 LOAD_NAME 并且排查

  • 找到字節(jié)碼狀態(tài)位置

  • 指令對(duì)應(yīng)著一個(gè)字節(jié)碼狀態(tài)值

  • https://github.com/python/cpython/blob/main/Lib/opcode.py

  • 這樣我們能否找到

  • 4 條指令分別對(duì)應(yīng)的字節(jié)狀態(tài)值

4 條指令

指令助記符

指令含義

十進(jìn)制狀態(tài)

十六進(jìn)制狀態(tài)

LOAD_NAME

裝載函數(shù)名稱

101

0x65

LOAD_CONST

裝載參數(shù)

100

0x64

CALL_FUNCTION

調(diào)用函數(shù)

142

0x8e

POP_TOP

彈棧返回

1

0x01

  • 可以找到源代碼的對(duì)應(yīng)關(guān)系么?

  • 好像找到了

  • 64XX

  • 64 00 是從表中的 00 號(hào)位置取得字符串 "Guido in cwi"

  • 64 01 是從表中的 01 號(hào)位置取字符串 "Guido in cnri"

  • ...

  • 以此類推,直到 05 83 取出字符串 "Guido in microsoft"

  • 0x83 對(duì)應(yīng)的是 GET_AWAITABLE

  • 可等待地調(diào)用

  • 那這些二進(jìn)制代碼究竟是什么指令集的呢?

  • 首先我們得弄懂什么是指令集呢?

指令集

  • 指令集 就是

  • 指令的集合

  • 上圖是 arm 的指令集

  • 也常被稱作 arm 架構(gòu)

  • 那什么又是架構(gòu)呢?

architect

  • architect 原本的英文含義是

  • 建筑

  • architecture

  • 造房子的人

  • 就是建筑師

  • 在 cpu 領(lǐng)域

  • architect

  • architecture

  • 指的是什么呢?

架構(gòu)師

  • 架構(gòu)師

  • 軟件開發(fā)行業(yè)從業(yè)者的終極形態(tài)

  • 非常硬核的存在

  • 那 python 的字節(jié)碼用的是什么架構(gòu)呢?

  • arm

  • 還是 x86 呢?

虛擬機(jī)的虛擬 cpu

  • pyc 的這些字節(jié)碼 (bytecode)

  • 對(duì)應(yīng)的是 python 虛擬機(jī)上面虛擬 cpu 的指令集

  • cpu 也能虛擬嗎?

  • 我們先把這節(jié)課總結(jié)一下

總結(jié)

  • 我們把 python 源文件

  • 詞法分析 得到 詞流 (token stream)

  • 語法分析 得到 抽象語法樹 (Abstract Syntax Tree)

  • 編譯 得到 字節(jié)碼 (bytecode)

  • 字節(jié)碼我們看不懂

  • 所以反編譯 得到 指令文件 (opcode)

  • 指令文件是基于 python 虛擬機(jī)的虛擬 cpu 的指令集

  • 什么是 python 虛擬機(jī)呢???

  • 我們下次再說??


  • 藍(lán)橋->https://www.lanqiao.cn/teacher/3584

    github->https://github.com/overmind1980/oeasy-python-tutorial

    gitee->https://gitee.com/overmind1980/oeasypython

    視頻->https://www.bilibili.com/video/BV1CU4y1Z7gQ 作者:oeasy 作者:oeasy https://www.bilibili.com/read/cv19181659 出處:bilibili



[oeasy]python0010 - python虛擬機(jī)解釋執(zhí)行py文件的原理的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國家法律
五台县| 利津县| 凌源市| 尉犁县| 江口县| 永泰县| 宿迁市| 余庆县| 汉阴县| 南乐县| 乌拉特前旗| 兴仁县| 朝阳区| 青川县| 汪清县| 凤庆县| 龙泉市| 乌兰县| 福建省| 灵寿县| 台南县| 措勤县| 神农架林区| 温泉县| 普兰县| 阿坝县| 东台市| 儋州市| 西城区| 精河县| 东丰县| 武定县| 青田县| 临泉县| 宝兴县| 张北县| 汉寿县| 景谷| 呼伦贝尔市| 岗巴县| 高雄市|