greenlet入门

什么是greenlet

greenlet是python的一个C扩展,提供了可自行调度的‘微线程’,即协程。

greenlet初体验

使用pip install greenlet即可安装。

假如有这样一个需求:
定义两个函数test1(),test2()。需要不断的在这两个函数中切换执行,我们如何使用greenlet来实现呢?在greenlet中非常容易,看代码。

from greenlet import greenlet


def test1():
    print("1")
    gr2.switch()
    print("3")
    gr2.switch()


def test2():
    print("2")
    gr1.switch()
    print("4")


if __name__ == "__main__":
    gr1 = greenlet(test1)
    gr2 = greenlet(test2)
    gr1.switch()

执行结果如下图:


image.png

然后我们整理一下逻辑,看看它是如何实现的?
首先我们定义了两个普通函数test1()和test2(),先不管内部实现了什么,先看程序入口,我们将两个定义好的函数分别传给greenlet(),并用gr1和gr2接受这两个结果,然后用gr1.switch()指定了从哪个协程开始执行。

其实看到这里,我们至少知道了它的执行顺序。我画了简图来帮助自己理解。


greenlet入门_第1张图片
image.png

当创建一个greenlet时,首先初始化一个空的栈,switch到这个栈时会传入函数,然后执行函数中的内容,直到遇到了另一个协程的switch命令(比如gr1.switch())将函数挂起,然后去gr1中上次中断的地方继续执行,以此类推。

一些思考

如果入口中没有gr1.switch()这句会怎么样?

入口中如果没有gr1.switch()这句会直接结束程序,因为这指定了从哪个greenlet开始执行。

如果去掉test1()中的最后一个gr2.switch(),为什么不会打印‘4’了?

因为switch表示切换协程,当去掉最后一个gr2.switch()后,直到test1执行完毕就结束了,不会再切换到test2()中继续执行了。


进一步了解greenlet

看看greenlet里面都有什么方法?
pprint(dir(greenlet))
greenlet入门_第2张图片
image.png

刨除那些魔法方法,剩的就不多了,先看看都是干啥的。

getcurrent()

这是一个全局函数,可以在任意地方获取当前正在执行的协程对象,比如我们修改之前的函数试试

from greenlet import greenlet, getcurrent


def test1():
    print("1")

    current_coroutine = getcurrent()
    print(current_coroutine)
    if gr1 is current_coroutine:
        print("this is gr1")

    gr2.switch()
    print("3")
    gr2.switch()


def test2():
    print("2")
    gr1.switch()
    print("4")


if __name__ == "__main__":
    gr1 = greenlet(test1)
    gr2 = greenlet(test2)
    gr1.switch()

结果打印了‘this is gr1’,这就说明我们拿到current_coroutine和gr1是同一个对象。

greenlet类

主要方法有getcurrent(), gettrace(), settrace(), switch(), throw()
属性有dead, gr_frame, parent, run, _stack_saved, error
gr.dead 返回true,表示协程已经结束。
gr.run 当greenlet启动时会调用这个callable,如果我们需要继承greenlet时,需要重写该方法。
throw 切换到执行协程后立即抛出异常。


先简单知道,以后慢慢补充~

你可能感兴趣的:(greenlet入门)