gevent是基于libev的并发库,它为各种并发和网络相关的任务提供了整洁的API
异步可以说是解决高并发程序的最高效的方法,多线程/多进程的切换开销巨大,特别是在很多线程进程的情况下
greenlet
在gevent总用到的主要模式是greenlet,是一种轻量级协程,通过C扩展模块接入python,greenlets(注意加了s代表很多)
全部运行在主程序所在的进程中,被协作式的调度
因为终究是单线程的,所以任何时刻只有一个协程在运行
而multiprocess和threading可以真正的实现并行
同步和异步执行
并发是操作系统的基本特征之一,这与共享性互为依存的。并发的核心思想是把大的任务分解成一系列小的子任务,子任务可以是同时(并行)执行或者异步执行而不是一次一个的同步执行。两个子任务之间进行上下文切换
在gevent中,上下文切换(也就是代码执行到别的行,不是函数跳转)是通过yielding来完成的,
gevent会自动识别有阻塞的地方,会对用户透明的进行上下文切换,切换到别的行执行,注意gevent.joinall(里面两个事件会有隐式的轮询,通过开启另一个协程),即使时sleep了0秒,它也认为这里有阻塞代码,于是进行切换
import gevent
def foo():
print('Running in foo')
gevent.sleep(0)
print('Explicit context switch to foo again')
def bar():
print('Explicit context to bar')
gevent.sleep(0)
print('Implicit context switch back to bar')
gevent.joinall([
gevent.spawn(foo),
gevent.spawn(bar),
])
当然我们也可以在很多可能发生阻塞操作的地方加上:yield from
import time
import gevent
from gevent import select
start = time.time()
tic = lambda: 'at %1.1f seconds' % (time.time() - start)
def gr1():
# Busy waits for a second, but we don't want to stick around...
print('Started Polling: %s' % tic())
select.select([], [], [], 2)
print('Ended Polling: %s' % tic())
def gr2():
# Busy waits for a second, but we don't want to stick around...
print('Started Polling: %s' % tic())
select.select([], [], [], 2)
print('Ended Polling: %s' % tic())
def gr3():
print("Hey lets do some s