标签: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