Python 程序的運(yùn)行原理

解釋型語(yǔ)言,由Python解釋器把源文件編譯為pyc文件(字節(jié)碼文件), 然后讓Python虛擬機(jī)去運(yùn)行字節(jié)碼

鏈接


2.2 編譯
執(zhí)行 python demo.py 后癣诱,將會(huì)啟動(dòng) Python 的解釋器乡翅,然后將 demo.py 編譯成一個(gè)字節(jié)碼對(duì)象 PyCodeObject狠怨。

有的人可能會(huì)很好奇项鬼,編譯的結(jié)果不應(yīng)是 pyc 文件嗎饵逐,就像 Java 的 class 文件,那為什么是一個(gè)對(duì)象呢笨奠,這里稍微解釋一下袭蝗。

在 Python 的世界中,一切都是對(duì)象般婆,函數(shù)也是對(duì)象到腥,類型也是對(duì)象,類也是對(duì)象(類屬于自定義的類型蔚袍,在 Python 2.2 之前乡范,int, dict 這些內(nèi)置類型與類是存在不同的配名,在之后才統(tǒng)一起來(lái),全部繼承自 object)晋辆,甚至連編譯出來(lái)的字節(jié)碼也是對(duì)象渠脉,.pyc 文件是字節(jié)碼對(duì)象(PyCodeObject)在硬盤上的表現(xiàn)形式。

在運(yùn)行期間瓶佳,編譯結(jié)果也就是 PyCodeObject 對(duì)象芋膘,只會(huì)存在于內(nèi)存中,而當(dāng)這個(gè)模塊的 Python 代碼執(zhí)行完后霸饲,就會(huì)將編譯結(jié)果保存到了 pyc 文件中为朋,這樣下次就不用編譯,直接加載到內(nèi)存中厚脉。pyc 文件只是 PyCodeObject 對(duì)象在硬盤上的表現(xiàn)形式习寸。

這個(gè) PyCodeObject 對(duì)象包含了 Python 源代碼中的字符串,常量值傻工,以及通過(guò)語(yǔ)法解析后編譯生成的字節(jié)碼指令霞溪。PyCodeObject 對(duì)象還會(huì)存儲(chǔ)這些字節(jié)碼指令與原始代碼行號(hào)的對(duì)應(yīng)關(guān)系,這樣當(dāng)出現(xiàn)異常時(shí)中捆,就能指明位于哪一行的代碼鸯匹。

2.3 pyc 文件
一個(gè) pyc 文件包含了三部分信息:Python 的 magic number、pyc 文件創(chuàng)建的時(shí)間信息泄伪,以及 PyCodeObject 對(duì)象忽你。

magic number 是 Python 定義的一個(gè)整數(shù)值。一般來(lái)說(shuō)臂容,不同版本的 Python 實(shí)現(xiàn)都會(huì)定義不同的 magic number科雳,這個(gè)值是用來(lái)保證 Python 兼容性的。比如要限制由低版本編譯的 pyc 文件不能讓高版本的 Python 程序來(lái)執(zhí)行脓杉,只需要檢查 magic number 不同就可以了糟秘。由于不同版本的 Python 定義的字節(jié)碼指令可能會(huì)不同,如果不做檢查球散,執(zhí)行的時(shí)候就可能出錯(cuò)尿赚。

下面所示的代碼可以來(lái)創(chuàng)建 pyc 文件,使用方法

python generate_pyc.py module_name
例如

python generate_pyc.py demo
[generate_pyc.pyc]
import imp
import sys

def generate_pyc(name):
fp, pathname, description = imp.find_module(name)
try:
imp.load_module(name, fp, pathname, description)
finally:
if fp:
fp.close()

if name == 'main':
generate_pyc(sys.argv[1])
2.4 字節(jié)碼指令
為什么 pyc 文件也稱作字節(jié)碼文件蕉堰?因?yàn)檫@些文件存儲(chǔ)的都是一些二進(jìn)制的字節(jié)數(shù)據(jù)凌净,而不是能讓人直觀查看的文本數(shù)據(jù)。

Python 標(biāo)準(zhǔn)庫(kù)提供了用來(lái)生成代碼對(duì)應(yīng)字節(jié)碼的工具 dis屋讶。dis 提供一個(gè)名為 dis 的方法冰寻,這個(gè)方法接收一個(gè) code 對(duì)象,然后會(huì)輸出 code 對(duì)象里的字節(jié)碼指令信息皿渗。

s = open('demo.py').read()
co = compile(s, 'demo.py', 'exec')
import dis
dis.dis(co)
執(zhí)行上面這段代碼可以輸出 demo.py 編譯后的字節(jié)碼指令

1 0 LOAD_CONST 0 (-1)
3 LOAD_CONST 1 (None)
6 IMPORT_NAME 0 (foo)
9 STORE_NAME 0 (foo)

3 12 LOAD_CONST 2 (1)
15 LOAD_CONST 3 (u'python')
18 BUILD_LIST 2
21 STORE_NAME 1 (a)

4 24 LOAD_CONST 4 (u'a string')
27 STORE_NAME 1 (a)

6 30 LOAD_CONST 5 (<code object func at 00D97650, file "demo.py", line 6>)
33 MAKE_FUNCTION 0
36 STORE_NAME 2 (func)

11 39 LOAD_NAME 1 (a)
42 PRINT_ITEM
43 PRINT_NEWLINE

13 44 LOAD_NAME 3 (name)
47 LOAD_CONST 6 (u'main')
50 COMPARE_OP 2 (==)
53 POP_JUMP_IF_FALSE 82

14 56 LOAD_NAME 2 (func)
59 CALL_FUNCTION 0
62 POP_TOP

15 63 LOAD_NAME 0 (foo)
66 LOAD_ATTR 4 (add)
69 LOAD_CONST 2 (1)
72 LOAD_CONST 7 (2)
75 CALL_FUNCTION 2
78 POP_TOP
79 JUMP_FORWARD 0 (to 82)
>> 82 LOAD_CONST 1 (None)
85 RETURN_VALUE
2.5 Python 虛擬機(jī)
demo.py 被編譯后斩芭,接下來(lái)的工作就交由 Python 虛擬機(jī)來(lái)執(zhí)行字節(jié)碼指令了轻腺。Python 虛擬機(jī)會(huì)從編譯得到的 PyCodeObject 對(duì)象中依次讀入每一條字節(jié)碼指令,并在當(dāng)前的上下文環(huán)境中執(zhí)行這條字節(jié)碼指令划乖。我們的程序就是通過(guò)這樣循環(huán)往復(fù)的過(guò)程才得以執(zhí)行贬养。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市琴庵,隨后出現(xiàn)的幾起案子误算,更是在濱河造成了極大的恐慌,老刑警劉巖迷殿,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尉桩,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡贪庙,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門翰苫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)止邮,“玉大人,你說(shuō)我怎么就攤上這事奏窑〉寂” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵埃唯,是天一觀的道長(zhǎng)撩匕。 經(jīng)常有香客問(wèn)我,道長(zhǎng)墨叛,這世上最難降的妖魔是什么止毕? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮漠趁,結(jié)果婚禮上扁凛,老公的妹妹穿的比我還像新娘。我一直安慰自己闯传,他們只是感情好谨朝,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著甥绿,像睡著了一般字币。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上共缕,一...
    開(kāi)封第一講書(shū)人閱讀 52,457評(píng)論 1 311
  • 那天洗出,我揣著相機(jī)與錄音,去河邊找鬼图谷。 笑死共苛,一個(gè)胖子當(dāng)著我的面吹牛判没,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播隅茎,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼澄峰,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了辟犀?” 一聲冷哼從身側(cè)響起俏竞,我...
    開(kāi)封第一講書(shū)人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎堂竟,沒(méi)想到半個(gè)月后魂毁,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡出嘹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年席楚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片税稼。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡烦秩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出郎仆,到底是詐尸還是另有隱情只祠,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布扰肌,位于F島的核電站抛寝,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏曙旭。R本人自食惡果不足惜盗舰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望桂躏。 院中可真熱鬧岭皂,春花似錦、人聲如沸沼头。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)进倍。三九已至土至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間猾昆,已是汗流浹背陶因。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留垂蜗,地道東北人楷扬。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓解幽,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親烘苹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子躲株,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容