标签:style http color io os 使用 ar for 文件
gevent core就是封装了libev,使用了cython的语法,感兴趣童鞋可以好好研究研究。其实libev是有python的封装
pyev(https://pythonhosted.org/pyev/),不过pyev是使用C来写扩展的,代码巨复杂。在看core.pyx代码之前先学习一下
core.pyx用到的cython知识。
cdef public class loop [object PyGeventLoopObject, type PyGeventLoop_Type]: cdef libev.ev_loop* _ptr cdef public object error_handler cdef libev.ev_prepare _prepare cdef public list _callbacks cdef libev.ev_timer _timer0你可能好奇,loop后面的中括号是干嘛用的?我们想想python中int类型的PyIntObject,
typedef struct { PyObject_HEAD long ob_ival; } PyIntObject;同样我们会生PyGeventLoopObject对象
struct PyGeventLoopObject { PyObject_HEAD struct __pyx_vtabstruct_6gevent_4core_loop *__pyx_vtab; struct ev_loop *_ptr; PyObject *error_handler; struct ev_prepare _prepare; PyObject *_callbacks; struct ev_timer _timer0; }
DL_EXPORT(PyTypeObject) PyGeventLoop_Type = { PyVarObject_HEAD_INIT(0, 0) __Pyx_NAMESTR("gevent.core.loop"), /*tp_name*/ sizeof(struct PyGeventLoopObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ __pyx_tp_dealloc_6gevent_4core_loop, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ ... }我们再来看看public的问题,这里的public也就是说这个class将会提供给其它.c文件使用,所以会生成对应的.h文件。
def __init__(self, object flags=None, object default=None, size_t ptr=0): passflags: 确定后端使用的异步IO模型,如"select, epoll",可直接字符串也可数字(需参考libev/ev.h)
from gevent import core flag = "select" loop=core.loop(flag) assert loop.backend == flag assert core._flags_to_int(flag) == loop.backend_int
def f(): print time.time() print ‘eeeee‘ from gevent.core import loop l = loop() timer = l.timer(2,3) #2秒后启动,3秒后再次启动 print time.time() timer.start(f) l.run()
def f(): raise ValueError(‘signal‘) sig = gevent.signal(signal.SIGALRM, f) assert sig.ref is False signal.alarm(1) try: gevent.sleep(2) raise AssertionError(‘must not run here‘) except ValueError: assert str(sys.exc_info()[1]) == ‘signal‘和其它watcher不同的是ref默认是False,因为信号并不是必须的,所以循环不需等待信号发生。
hub = gevent.get_hub() watcher = hub.loop.async() gevent.spawn_later(0.1, thread.start_new_thread, watcher.send, ()) start = time.time() with gevent.Timeout(0.3): hub.wait(watcher)gevent中线程池中使用了async,当worker线程运行回调函数后,设置返回值,通过async.send唤醒hub主线程
self.fork_watcher = hub.loop.fork(ref=False) self.fork_watcher.start(self._on_fork) def _on_fork(self): # fork() only leaves one thread; also screws up locks; # let‘s re-create locks and threads pid = os.getpid() if pid != self.pid: self.pid = pid # Do not mix fork() and threads; since fork() only copies one thread # all objects referenced by other threads has refcount that will never # go down to 0. self._init(self._maxsize)回调_on_fork目的就是重新初始化线程池,但是刚才说了子进程要有效必须要调用libev.ev_loop_fork,
if hasattr(os, ‘fork‘): _fork = os.fork def fork(): result = _fork() if not result: #子进程 reinit() #调用libev.ev_loop_fork return result问题的关键就是gevent/os.py中重定义了fork函数,当fork返回0,也就是子进程,将调用reinit
def reinit(self): if self._ptr: libev.ev_loop_fork(self._ptr)gevent中的线程池在gevent中使用的很广,尤其是windows中,如dns请求,os.read write都是通过线程池,
1.loop.run_callback会向loop._callbacks中添加回调 2.在loop的__init__中初始化prepare: libev.ev_prepare_init(&self._prepare, <void*>gevent_run_callbacks) 注册回调为gevent_run_callbacks 3.在gevent_run_callbacks中会调用loop的_run_callbacks result = ((struct __pyx_vtabstruct_6gevent_4core_loop *)loop->__pyx_vtab)->_run_callbacks(loop); 4.loop的_run_callbacks中会逐个调用_callbacks中的回调这也就是为什么说callback优先级高的原因。
def f(a): a.append(1) from gevent.hub import get_hub loop = get_hub().loop a= [] f = loop.run_callback(f,a) f.stop() gevent.sleep(0) assert not f.pending #没有阻塞可能是已运行或被停止 assert not a如果注释掉f.stop(),那么a是[1],因为gevent.sleep(0)也是直接run_callback,肯定是谁先加入谁先调用,
开两个窗口,一个运行该程序,另一个可touch cs.log文件,文件有无也是状态变化 hub = gevent.get_hub() filename = ‘cs.log‘ watcher = hub.loop.stat(filename,2) #2s以后才监听文件状态 def f(): print os.path.exists(filename) watcher.start(f) gevent.sleep(100)
int ev_run (EV_P_ int flags) { do { ...... } while (expect_true ( activecnt && !loop_done && !(flags & (EVRUN_ONCE | EVRUN_NOWAIT)) )); return activecnt; }其中activecnt就是我们上面说的loop的引用计数,所以除非特殊情况ref最好为True。
[gevent源码分析] libev cython绑定core.pyx
标签:style http color io os 使用 ar for 文件
原文地址:http://blog.csdn.net/yueguanghaidao/article/details/39253645