视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
pythongevent实现机制
2020-11-27 14:27:21 责编:小采
文档


之前看的greenlet只是提供了基本的coroutine的作用,是最小的执行单元.但是要想使用,还需要提供一个调度器,来调度什么时候哪些greenlet应该执行.所以看了一下gevent的实现,当前的稳定版本使用的是libev.libevent的一种替代方案.性能上更优越一些.libev支持很多事件类型,但是最常用的是io和timer类型的.io类型的通过系统提供的相关系统调用实现(linux下是epoll),timer类型的通过维护一个最小堆实现.
看一下下面的代码:

Python代码

import gevent 
from gevent import monkey 
monkey.patch_all() 
 
def download(): 
 import urllib2 
 urllib2.urlopen('http://www.google.com/').read() 
 
c = gevent.spawn(download) 
gevent.joinall([c])

gevent通过spawn创建并启动一个greenlet,此greenlet执行函数为download.启动这个greenlet是通过把这个greenlet加入到libev的prepare callback里面.libev在每次执行事件循环的时候都会调用prepare callback里面的函数,执行后把里面的callback清除掉.这样就能保证每次spawn的greenlet有执行的机会.并且只会执行一次.
在这个greenlet执行urlopen以及read的时候,因为涉及到io操作(socket.[send|recv]),gevent通过monkey patch把这些函数进行了封装,当调用相关的操作时就会创建一个对应fd的watcher加入到libev的事件列表里面.
当有相关的读写事件发生时,会触发相应的callback.相关的callback会调用greenlet的switch进行coroutine的切换.
通过上面的方式greenlet达到了调度器的目的.

下载本文
显示全文
专题