sleep函数——Gevent源码分析

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

gevent是一个异步I/O框架,当遇到I/O操作的时候,会自动切换任务,从而能异步地完成I/O操作

但是在测试的情况下,可以使用sleep函数来让gevent进行任务切换。示例如下:

import gevent

def test(id):PRint('Test %s is running...' % id)

gevent.sleep(0)

print('Test %s is done!' % id)

gevent.joinall([gevent.spawn(test, i) for i in range(2)])

该函数的执行结果是:

Test 0 is running...

Test 1 is running...

Test 0 is done!

Test 1 is done!

可见,sleep函数能让gevent切换协程,进行异步操作。

这次我想探究一下sleep函数的原理。

在了解sleep函数之前,我们需要了解一下gevent的运行

在前面的文章中,我们知道了gevent有个主协程hub的概念,当需要切换协程的时候,需要先回到hub,然后再由hub去切换。

其实主协程hub是一个特殊的协程Greenlet。

当gevent运行的时候,gevent需要先创建一个主协程hub,并运行hub的run函数(具体源码在hub.py/run),比较简单,核心代码是loop.run(),这个run函数是Greenlet类中的run函数,用来切入loop中的子协程,源码在greenlet.py/run中。核心就是result = self._run(*self.args, **self.kwargs),_run函数用来执行这个子协程的任务

sleep函数在刚刚的示例代码中,在sleep处设置断点,进行跟踪。

首先,进入sleep函数,函数在hub.py中:

def sleep(seconds=0, ref=True):

hub = get_hub()#获得主协程hub对象

loop = hub.loop#获得主循环

if seconds <= 0:

waiter = Waiter()

loop.run_callback(waiter.switch)#设置回调函数(即下次本协程执行的地点)

waiter.get()

else:

hub.wait(loop.timer(seconds, ref=ref))

当seconds=0的时候,loop.run_callback(waiter.switch)把当前greenlet的switch注册到loop中,设置为回调函数,此时的loop是主协程hub下的loop。

sleep函数中最后调用了waiter.get(),get函数简化如下:

def get(self):

assert self.greenlet is None, 'This Waiter is already used by %r' % (self.greenlet, )

self.greenlet = getcurrent()

try:

return self.hub.switch()

finally:

self.greenlet = None

self.greenlet = getcurrent(): 把greenlet设置为当前协程greenlet

return self.hub.switch(): 切换到主线程hub的主循环, 然后主循环再切换到下一个greenlet协程

工作流程如图:

总结Gevent的工作原理(省略了执行完协程之后的过程)如下:

程序启动,需要创建主协程hub

主协程执行hub.run()函数,里面主要是执行loop.run(),loop中是子协程,相当于执行子协程的run()函数

切换到子协程,执行Greenlet.run()函数

在Greenlet.run()函数中,执行到self._run()函数,即执行该协程的任务,本例中为自己定义的test()函数

一直执行到sleep(0)语句

在sleep()函数中保存回调的位置(即保存该协程执行到的地方),调用waiter.get()函数

waiter.get()函数将调用self.hub.switch()切回主协程hub

hub.switch()将调用greenlet.switch()函数:

如果即将切换的协程未执行过run函数,则执行run函数;

如果执行过run函数,则调用Waiter.switch()函数接着上次执行的地方执行重复以上的过程,直至所有协程任务全部执行完毕

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航