我試圖通過跟蹤不同的字節碼/操作碼來加深對CPython解釋器的理解,因爲他們通過ceval.c
的解釋器循環執行簡單的Python程序。我使用bytecode
和opcode
來表示同樣的事情。通過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
中的不同opcode
的switch
聲明,開始於第964行。
我在for
循環開始後添加了這些行,以檢查解釋器是否正在運行我的文件,如果是,則打印出opcode
。
964 for (;;) {
965 if (strcmp(filename, "../test.py") == 0) {
966 printf("%d\n", opcode);
967 }
和輸出我得到的是(手動添加註釋,以顯示從opcode.h
opcode
DEFINE
的):
$ ./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
包的不同操作碼?
我認爲當你的意思是「CPython」(「標準」Python解釋器)時,你錯誤地將它標記爲「Cython」(一種將Python類語言轉換爲C以增加數值計算速度的工具)。就目前而言,這個問題沒有太大意義... – DavidW
但是忽略了你看到的字節碼不一樣的事實我認爲你期望得到不同數量的字節碼:ceval中的循環只顯示執行的東西(不是部分「it/else」會被忽略),而dis會給你一切。 – DavidW
可能的重複[什麼是對PyObjC應用程序進行採樣/配置文件的最佳方式?](http://stackoverflow.com/questions/157662/what-is-the-best-way-to-sample-profile-a- pyobjc的應用程序) –