2013-10-24 43 views
15

我很難理解Python的字節碼及其dis模塊。如何讀取python字節碼?

import dis 
def func(): 
    x = 1 
dis.dis(func) 

在解釋器輸入時,以上代碼產生以下輸出:

0 LOAD_CONST     1(1) 
    3 STORE_FAST     0(x) 
    6 LOAD_CONST     0(NONE) 
    9 RETURN_VALUE 

例如:

什麼是LOAD_CONSTSTORE_FAST的含義和等0數字,369

一個特定的資源,我可以找到這個信息將不勝感激。

+0

我不確定你是否閱讀這個答案http://stackoverflow.com/a/12673195/973699 – DevC

+0

@DevC我讀了這個問題,但問題是,我只是想解釋一個非常「簡單」的功能,就像我在我的問題中提到的那樣,這樣我至少可以對字節碼中發生的事情有一個小小的認識。 –

回答

29

的字節碼前的數字是偏移到原始的二進制字節碼:

>>> func.__code__.co_code 
'd\x01\x00}\x00\x00d\x00\x00S' 

一些字節碼伴隨着額外的信息(參數)影響了每個字節碼的作品,偏移告訴你在字節流的什麼位置字節碼被找到。

LOAD_CONST的字節碼(ASCII d,十六進制64),接着通過編碼與字節碼相關聯,例如一個恆定的基準兩個額外的字節。因此,在索引3處找到STORE_FAST操作碼(ASCII },十六進制7D)。

dis module documentation列出了每條指令的含義。對於LOAD_CONST,它說:

co_consts[consti]推到堆棧上。

它是指co_consts結構總是與代碼對象一起出現;編譯器構建的是:

>>> func.__code__.co_consts 
(None, 1) 

從結構(在字節碼編碼一個1 01 00字節),並且dis操作碼負荷指數1已經看,多達你;它是值1

下一條指令,STORE_FAST被描述爲:

商店TOS到本地co_varnames[var_num]

這裏TOS指的是棧頂;請注意,LOAD_CONST只是推動東西到堆棧上,1值。 co_varnames是另一種結構;它引用局部變量名,操作碼引用索引0:

>>> func.__code__.co_varnames 
('x',) 

dis看着那起來過,你在你的代碼中使用的名稱是x。因此,該操作碼將1存儲爲x

LOAD_CONST另一個負載None到堆棧從索引0,接着RETURN_VALUE

返回具有TOS給函數的調用者。

所以這條指令佔用棧頂(None常量),並從這個代碼塊返回。 None是沒有明確的return語句的函數的默認返回值。

您省去從dis輸出,東西行號:

>>> dis.dis(func) 
    2   0 LOAD_CONST    1 (1) 
       3 STORE_FAST    0 (x) 
       6 LOAD_CONST    0 (None) 
       9 RETURN_VALUE   

注意2第一線;這是原始源代碼中包含用於這些指令的Python代碼的行號。 Python代碼對象具有co_lnotabco_firstlineno屬性,可讓您將字節碼映射回原始源代碼中的行號。顯示反彙編時,dis會爲您做這件事。

+0

感謝您的廣泛答覆和對文檔的參考 –