gevent是一个强大且高效的异步I/O框架,它基于greenlet实现协程,并提供了一种类似事件驱动的编程模型。通过将阻塞操作转换为非阻塞,gevent能够充分利用系统资源,处理大量并发连接,尤其适用于网络和I/O密集型应用。

gevent的核心是其对Greenlet的利用,这是一种轻量级线程(比Python的线程更高效),可以在同一进程中快速切换上下文。当一个Greenlet执行到阻塞操作(如网络IO)时,gevent会自动切换到另一个就绪的Greenlet,从而实现无阻塞的并发执行。

       由于IO操作非常耗时,经常使程序处于等待状态,gevent能自动切换协程,这样总保证有greenlet在运行,而非等待IO操作,因此效率一般比纯粹多线程高。gevent需要修改python自带的一些标准库,将一些常见的阻塞,如socket、select等地方实现协程跳转,这是在启动时通过monkey patch完成的。

gevent主要特性

1 基于libev的快速事件循环,linux上是epoll机制。

2 基于greenlet的轻量级执行单元。

3 API复用了python标准库里面打的内容

4支持SSL的协作式sockets

5 可通过线程池或c-ares实现DNS查询

6 通过monkey patching功能使得第三方模块变成协作式。

 

例子1:gevent的spawn方法作用是形成协程,joinall方法作用是添加这些协程任务。

from gevent.monkey import patch_allfrom gevent import monkeyimport geventimport urllib.requestimport time


def run_task(url):
   
print('访问-->%s,开始时间%s'%(url,time.time()))
   
try:
        response = urllib.request.urlopen(url)
        data = response.read()
       
print('%d bytes received from %s,结束时间%s.'%(len(data),url,time.time()))
   
except Exception as e:
       
print(e)

if __name__=='__main__':
    urls = [
'https://www.baidu.com/','https://www.cnblogs.com/','https://www.csdn.net/']
    greenlets = [gevent.spawn(run_task,url)
for url in urls]
    gevent.joinall(greenlets)

 

用gevent库实现协程_多线程

结果:

从时间上看,是并发处理的,但是结束的顺序不同,其实是一个线程在处理。

例子2:gevent中对池的支持。一般在需要处理动态数量的greenlet并发时,使用池。

from gevent import monkeyfrom gevent.pool import Pool
monkey.patch_all()
import urllib.requestimport time


def run_task(url):
   
print('访问-->%s,开始时间%s'%(url,time.time()))
   
try:
        response = urllib.request.urlopen(url)
        data = response.read()
       
print('%d bytes received from %s,结束时间%s.'%(len(data),url,time.time()))
   
except Exception as e:
       
print(e)
   
return 'url:%s--->完成'%url

if __name__=='__main__':
    pool = Pool(
2)
    urls = [
'https://www.baidu.com/','https://www.cnblogs.com/','https://www.csdn.net/']
    results = pool.map(run_task,urls)
   
print(results)

 

结果:

用gevent库实现协程_python标准库_02

可以看到一次执行两个任务。