摘要:不過不管怎樣,就當多學習了一些其他知識,況且分析源碼肯定少不了對這些知識的了解。官方文檔描述里面提到了,在這個模塊中指的就是,一般稱它為方法列表。返回一個指向它創建的模塊對象的指針。
在greenlet篇中只是簡單講述了一下greenlet原理,不知道有沒有人對源碼感興趣的,不過我還是比較感興趣的。對于技術我一直都覺得『知其然,知其所以然』才是最好的,不希望自己只停留在知道用,而不知道為什么這樣用。
一篇可能介紹不完,所以可能需要分幾部分來介紹。當我寫到這的時候突然發現自己是不是寫跑題了,本來是寫greenlet源碼分析的,結果變成了怎么去寫Python擴展了。不過不管怎樣,就當多學習了一些其他知識,況且分析源碼肯定少不了對這些知識的了解。
模塊初始化greenlet是用C編寫的一個擴展模塊,即用Python去調用C程序。像下面這段代碼,內部都是怎樣的一個過程呢?
from greenlet import greenlet def test1(): print 12 gr2.switch() print 34 def test2(): print 56 gr1.switch() print 78 gr1 = greenlet(test1) gr2 = greenlet(test2) gr1.switch()
這段代碼中,我們看到from greenlet import greenlet這句,相信都能明白是導入了一個模塊。為什么要導入這個模塊呢?這個問題有點瞧不起大家了,因為我們可能需要使用這個模塊的某個功能。那在導入這個模塊的時候,Python解釋器需要做哪些工作呢?在使用一個類的時候,我們肯定是需要調用構造函數來初始化的,導入模塊就類似于這樣的一個初始化過程。所以肯定會有一個初始化函數,它長啥樣?
在文檔中有這樣一句:The initialization function must be named initname(), where name is the name of the module, and should be the only non-static item defined in the module file.
所以對于greenlet,我們就能找到initgreenlet(void)函數。
#define INITERROR return // 第一次導入greenlet模塊時調用 PyMODINIT_FUNC initgreenlet(void) { PyObject* m = NULL; char** p = NULL; PyObject *c_api_object; static void *_PyGreenlet_API[PyGreenlet_API_pointers]; GREENLET_NOINLINE_INIT(); m = Py_InitModule("greenlet", GreenMethods); if (m == NULL) { INITERROR; } ... }
首先根據模塊名查找相應的初始化函數,然后Py_InitModule()函數向Python解釋器注冊該模塊中所有可以用到的方法。而Py_InitModule()函數是由Python提供的C API,對于使用C API只需要包含一個頭文件就可以了。
官方文檔描述:All function, type and macro definitions needed to use the Python/C API are included in your code by the following line:
#include "Python.h"方法列表
看下關鍵代碼m = Py_InitModule("greenlet", GreenMethods)。官方文檔描述:Create a new module object based on a name and table of functions, returning the new module object.
里面提到了table of functions,在這個模塊中指的就是GreenMethods,一般稱它為方法列表。該列表給出了所有可以被Python解釋器使用的方法,將這些方法注冊到這個模塊中,這樣在我們導入模塊后就可以直接使用了。
當Python程序第一次導入greenlet模塊的時候,調用initgreenlet()函數。接著Py_InitModule()會創建一個“模塊對象”(它將被插入到sys.modules字典下的“greenlet”鍵下),并且將方法列表(PyMethodDef結構數組)構成的內建函數對象作為它的第二個參數傳到剛被創建的模塊中。Py_InitModule()返回一個指向它創建的模塊對象的指針。方法列表代碼:
static PyMethodDef GreenMethods[] = { {"getcurrent", (PyCFunction)mod_getcurrent, METH_NOARGS, /*XXX*/ NULL}, ... };
方法列表中的各項參數如下:
(PyCFunction)mod_getcurrent函數如下:
static PyObject* mod_getcurrent(PyObject* self) { if (!STATE_OK) return NULL; Py_INCREF(ts_current); return (PyObject*) ts_current; }
該函數的作用就是獲取當前greenlet對象,并添加引用計數。
小結一個模塊的初始化工作大致是這樣的。不過針對greenlet發現了一些問題,在該模塊的方法列表中看到了getcurrent,而其他像switch、run等卻沒有看到。隨后去查閱greenlet的官方文檔,看到了greenlet.getcurrent()和g.switch(*args, **kwargs),卻被分別安排在『實例化』和『greenlets的方法和屬性』兩個不同的標題之下,為什么要這樣區分呢?
以上部分都是一個Python C擴展模塊基本的初始化工作,針對greenlet還有其他要做的。具體怎么做以及上面問題的答案就放到下一篇講吧,因為內容比較多在這篇講不完。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/37422.html
摘要:怎么記錄呢這里就可以回到上面我們需要了解的幾個棧操作了。這個時候,如果函數執行完了想去執行函數的時候,就按照這個流程再保存,然后再把剛才存放的函數給復制到棧中。 showImg(http://young-py.github.io/imgs/yyzt2.jpg); gevent文檔:that uses greenlet to provide a high-level synchrono...
摘要:一旦有事件產生可能是一次出現好多個事件,就會按照優先級依次調用每個事件的回調函數。注意,是有超時的,所以一些無法以文件描述符的形式存在的事件也可以有機會被觸發。 這一篇主要想跟大家分享一下 Gevent 實現的基礎邏輯,也是有同學對這個很感興趣,所以貼出來跟大家一起分享一下。 Greenlet 我們知道 Gevent 是基于 Greenlet 實現的,greenlet 有的時候也被...
摘要:隨著我們對于效率的追求不斷提高,基于單線程來實現并發又成為一個新的課題,即只用一個主線程很明顯可利用的只有一個情況下實現并發。作為的補充可以檢測操作,在遇到操作的情況下才發生切換協程介紹協程是單線程下的并發,又稱微線程,纖程。 引子 之前我們學習了線程、進程的概念,了解了在操作系統中進程是資源分配的最小單位,線程是CPU調度的最小單位。按道理來說我們已經算是把cpu的利用率提高很多了。...
摘要:所以與多線程相比,線程的數量越多,協程性能的優勢越明顯。值得一提的是,在此過程中,只有一個線程在執行,因此這與多線程的概念是不一樣的。 真正有知識的人的成長過程,就像麥穗的成長過程:麥穗空的時候,麥子長得很快,麥穗驕傲地高高昂起,但是,麥穗成熟飽滿時,它們開始謙虛,垂下麥芒。 ——蒙田《蒙田隨筆全集》 上篇論述了關于python多線程是否是雞肋的問題,得到了一些網友的認可,當然也有...
摘要:協程,又稱微線程,纖程。最大的優勢就是協程極高的執行效率。生產者產出第條數據返回更新值更新消費者正在調用第條數據查看當前進行的線程函數中有,返回值為生成器庫實現協程通過提供了對協程的基本支持,但是不完全。 協程,又稱微線程,纖程。英文名Coroutine協程看上去也是子程序,但執行過程中,在子程序內部可中斷,然后轉而執行別的子程序,在適當的時候再返回來接著執行。 最大的優勢就是協程極高...
閱讀 2655·2021-11-24 10:44
閱讀 1896·2021-11-22 13:53
閱讀 1907·2021-09-30 09:47
閱讀 3704·2021-09-22 16:00
閱讀 2431·2021-09-08 09:36
閱讀 2312·2019-08-30 15:53
閱讀 2790·2019-08-30 15:48
閱讀 976·2019-08-30 15:44