背景介紹
要深入一門語言,光知道編寫業務很難深入。必須知道其內部原理才能寫出更加優質的代碼,特別是當設計到高並發程序的時候,你需要理解為什么有時候我們的多線程並不一定能夠獲得理想的效率,也許你知道GIL鎖,但是不知道為什么它要存在?你也許知道可以通過使用多進程來替換多線程從而避免GIL但是你不知道我們還可以寫C模塊,然后用Python特有的膠水特性調用C從而避免GIL鎖。當然說了那么多,總之就是想說我們需要深入Python,那么要深入一樣東西必須找好入口,這個入口一旦找到就很容易思考各個模塊的作用是什么了。
預備知識
因為不是人人都有Mac電腦,我就使用Linux來做演示,並且使用的是ubuntu版本。下面是准備系統編譯環境
下載代碼:
git clone https://github.com/python/cpython
cd cpython
git checkout <tag name> # 當前最新的tagid
構建工具安裝,包含了gcc和make等
sudo apt install build-essential
接下來安裝一些依賴庫:
sudo apt install libssl-dev zlib1g-dev libncurses5-dev \
libncursesw5-dev libreadline-dev libsqlite3-dev libgdbm-dev \
libdb5.3-dev libbz2-dev libexpat1-dev liblzma-dev libffi-dev
配置及編譯
為了在后續調試方便,我們在配置的時候選擇一個debug模式,這樣會打印更多日志讓我們參考:
./configure --with-pydebug
運行沒有錯誤的話,可以進行下一步:
make -j2 -s
j2代表啟動兩個job來加速編譯,如果你CPU數量足夠可以開啟更多個,-s代表silent安靜的編譯,即不打印消息。
運行測試
如果編譯沒有錯誤,這時候應該會在當前目錄下生成一個python可以執行文件。
./python既可以運行

編寫模塊
要編寫自己的模塊需要遵循一定的規則,這些規則包含了內部定義的輸入輸出,錯誤日志及內存管理等。
進入到源碼的cpython/Modules/目錄下,建立hellomodule.c文件,然后開始擼代碼。
#define PY_SSIZE_T_CLEAN
#include <Python.h>
static PyObject *
say_hello_ak(PyObject *self, PyObject *args)
{
const char * greeting = "hello\n";
int sts;
sts = printf("%s", greeting);
return PyLong_FromLong(sts);
}
static PyMethodDef helloMethods[] = {
{"say", say_hello_ak, METH_VARARGS, "say hello to frank ak .."},
{NULL, NULL, 0, NULL}
};
PyDoc_STRVAR(hello_doc, "this module is for someone who want to deep learn Python.\n\n ");
static struct PyModuleDef hellomodule = {
PyModuleDef_HEAD_INIT,
"hello",
hello_doc,
-1,
helloMethods
};
PyMODINIT_FUNC
PyInit_hello(void)
{
return PyModule_Create(&hellomodule);
}
在/Modules/Setup.local中注冊,讓編譯器知道有新的模塊需要添加。
# Edit this file for local setup changes
hello hellomodule.o
在/Modules/config.c中添加模塊映射:
/* AK Add Module */
extern PyObject* PyInit_hello(void);
添加映射:
// ....
/* This lives in Objects/unicodeobject.c */
{"_string", PyInit__string},
/* AK registered Module */
{"hello", PyInit_hello},
/* Sentinel */
{0, 0}
再次編譯
make
測試模塊

總結
通過源代碼構建自己的Python,然后編寫一個模塊認識模塊編寫規則,最好測試模塊。這篇文章主要是先快速的讓大家看到編寫模塊的流程,很多函數定義及規則沒有細說,細心的讀者或許看到我的Python終端顯示了一個不同的圖案,那是我在測試另一外一個功能的時候寫入的,后續會介紹。
