摘要:不过不管怎样,就当多学习了一些其他知识,况且分析源码肯定少不了对这些知识的了解。官方文档描述里面提到了,在这个模块中指的就是,一般称它为方法列表。返回一个指向它创建的模块对象的指针。
在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还有其他要做的。具体怎么做以及上面问题的答案就放到下一篇讲吧,因为内容比较多在这篇讲不完。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/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协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。 最大的优势就是协程极高...
阅读 2628·2021-11-24 10:44
阅读 1852·2021-11-22 13:53
阅读 1877·2021-09-30 09:47
阅读 3682·2021-09-22 16:00
阅读 2412·2021-09-08 09:36
阅读 2296·2019-08-30 15:53
阅读 2773·2019-08-30 15:48
阅读 937·2019-08-30 15:44