2015-11-11 39 views
0

我試圖通過跟蹤不同的字節碼/操作碼來加深對CPython解釋器的理解,因爲他們通過ceval.c的解釋器循環執行簡單的Python程序。我使用bytecodeopcode來表示同樣的事情。通過CPython執行跟蹤Python字節碼

我的Python程序是這樣的:

#filename: test.py 

x = 2 
y = 3 

if x < y: 
    z = x 
elif True: 
    z = y 
else: 
    z = 100 

我使用Python 2.7.8,並與調試標誌建造它,像這樣:

wget https://www.python.org/ftp/python/2.7.8/Python-2.7.8.tgz # download 
tar xvf Python-2.7.8.tgz          # extract 
cd Python2.7.8 
./configure --with-pydebug          # build with debug flag 
make -j               # parallel make 

我感興趣的是通過for(;;)跟蹤循環包括在解釋器循環ceval.c中的不同opcodeswitch聲明,開始於第964行。

我在for循環開始後添加了這些行,以檢查解釋器是否正在運行我的文件,如果是,則打印出opcode

964  for (;;) { 
965   if (strcmp(filename, "../test.py") == 0) { 
966    printf("%d\n", opcode); 
967   } 

和輸出我得到的是(手動添加註釋,以顯示從opcode.hopcodeDEFINE的):

$ ./python.exe ../test.py | cat -n            
1 0 // STOP_CODE 
2 90 // HAVE_ARGUMENT 
3 90 // HAVE_ARGUMENT 
4 101 // LOAD_NAME 
5 101 // LOAD_NAME 
6 101 // LOAD_NAME 
7 90 // STORE_NAME 

我預計12點不同的操作碼,而不是7,因爲當我得到的字節碼拆卸有相同的文件,有12個字節碼命令。

$ ./python.exe -m dis ../pytests/test.py | sed "/^$/d" | cat -n      
1 1   0 LOAD_CONST    0 (2) 
2    3 STORE_NAME    0 (x) 
3 2   6 LOAD_CONST    1 (3) 
4    9 STORE_NAME    1 (y) 
5 4   12 LOAD_NAME    0 (x) 
6    15 LOAD_NAME    1 (y) 
7    18 COMPARE_OP    0 (<) 
8    21 POP_JUMP_IF_FALSE  33 
9 5   24 LOAD_NAME    0 (x) 
10    27 STORE_NAME    2 (z) 
11    30 JUMP_FORWARD   21 (to 54) 
12 6  >> 33 LOAD_NAME    

我的interpeter工作CPython的和/或登錄我在不同的操作碼的方法是如何不正確,或兩者的心智模式。你能解釋爲什麼我看到來自ceval.c文件的輸出和使用python -m dis包的不同操作碼?

+0

我認爲當你的意思是「CPython」(「標準」Python解釋器)時,你錯誤地將它標記爲「Cython」(一種將Python類語言轉換爲C以增加數值計算速度的工具)。就目前而言,這個問題沒有太大意義... – DavidW

+0

但是忽略了你看到的字節碼不一樣的事實我認爲你期望得到不同數量的字節碼:ceval中的循環只顯示執行的東西(不是部分「it/else」會被忽略),而dis會給你一切。 – DavidW

+1

可能的重複[什麼是對PyObjC應用程序進行採樣/配置文件的最佳方式?](http://stackoverflow.com/questions/157662/what-is-the-best-way-to-sample-profile-a- pyobjc的應用程序) –

回答

0

您的跟蹤顯示有問題,因爲在正常情況下,您不會執行任何會停止執行的STOP_CODE(值0)。另外,HAVE_ARGUMENT不是操作碼。對於Python 2.7,操作碼是STORE_NAME

至於值的差異,這是在任何代碼不是直線(基本塊)代碼預計。而你的不是直線代碼。有一個COMPARE <後跟一個POP_JUMP_IF_FALSE跳。