专栏名称: Python开发者
人生苦短,我用 Python。伯乐在线旗下账号「Python开发者」分享 Python 相关的技术文章、工具资源、精选课程、热点资讯等。
目录
相关文章推荐
Python开发者  ·  震撼!美国卡脖子下,中国工程师拖 4 ... ·  10 小时前  
Python爱好者社区  ·  又见车企远程锁车?车主无奈,网友怒喷“谁敢买” ·  昨天  
Python开发者  ·  年薪96w!又一新兴岗位崛起!这才是开发人未 ... ·  18 小时前  
Python开发者  ·  三大云厂同时瘫了?Cursor、ChatGP ... ·  昨天  
51好读  ›  专栏  ›  Python开发者

Gevent 调度流程解析

Python开发者  · 公众号  · Python  · 2017-09-28 19:55

正文

请到「今天看啥」查看全文


()


形参watcher就是loop.timer实例,其cython描述在corecext.pyx,我们简单理解成是一个定时器事件就行了。上面的代码中,创建了一个Waiter(gevent.hub.Waiter)对象,这个对象起什么作用呢,这个类的doc写得非常清楚:


Waiter . __doc_ _

A low level communication utility for greenlets .

Waiter is a wrapper around greenlet ' s `` switch ()`` and `` throw ()`` calls that makes them somewhat safer :

* switching will occur only if the waiting greenlet is executing : meth : ` get ` method currently ;

* any error raised in the greenlet is handled inside : meth : ` switch ` and : meth : ` throw `

* if : meth : ` switch ` /: meth : ` throw ` is called before the receiver calls : meth : ` get `, then : class : ` Waiter `

will store the value / exception . The following : meth : ` get ` will return the value / raise the exception


简而言之,是对greenlet.greenlet类switch 和 throw函数的分装,用来存储返回值greenlet的返回值或者捕获在greenlet中抛出的异常。我们知道,在原生的greenlet中,如果一个greenlet抛出了异常,那么该异常将会展开至其parent greenlet。


回到Hub.wait函数,第8行 watcher.start(waiter.switch, unique) 注册了一个回调,在一定时间(1s)之后调用回调函数waiter.switch。注意,waiter.switch此时并没有执行。然后第10行调用waiter.get。看看这个get函数(gevent.hub.Waiter.get):


def get ( self ) :

"""If a value/an exception is stored, return/raise it. Otherwise until switch() or throw() is called."""

if self . _exception is not _NONE :

if self . _exception is None :

return self . value

else :

getcurrent (). throw ( * self . _exception )

else :

if self . greenlet is not None :

raise ConcurrentObjectUseError ( 'This Waiter is already used by %r' % ( self . greenlet , ))

self . greenlet = getcurrent () # 存储当前协程,之后从hub switch回来的时候使用

try :

return self . hub . switch () # switch到hub

finally :

self . greenlet = None


核心的逻辑在第11到15行,11行中,getcurrent获取当前的greenlet(在这个测试代码中,是main greenlet,即最原始的greenlet),将其复制给waiter.greenlet。然后13行switch到hub,在greenlet回顾章节的第二条提到,greenlet.greenlet的子类需要重写run方法,当调用子类的switch时会调用到该run方法。Hub的run方法实现如下:


def run ( self ) :

"""

Entry-point to running the loop. This method is called automatically

when the hub greenlet is scheduled; do not call it directly.







请到「今天看啥」查看全文