Python 协程 gevent

gevent 封装的 greenlet, greenlet 封装的 yield( 即:生成器)。

通过 gevent.spawn() 创建一个 greenlet 对象,通过 greenlet 进行 switch,调用 yield。

gevent.spawn(函数,参数)

gevent 在遇到延时操作(gevent.sleep(0))时,先去执行别的。

如果你想用 gevent, 那需要把所有的延时操作换成 gevent.sleep(0) 或者通过打补丁的方式让程序自动替换。

如果一个线程等待某些条件,可以充分利用这个时间去做其它事情,其实这就是协程。

1
2
from gevent import monkey
monkey.patch_all()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import gevent
import time
from gevent import monkey

monkey.patch_all()

def f(n):
for i in range(n):
print(gevent.getcurrent(), i)
time.sleep(0)


g1 = gevent.spawn(f, 5)
g2 = gevent.spawn(f, 5)
g3 = gevent.spawn(f, 5)
g1.join()
# 程序运行到这里之后,阻塞延迟,于是去运行上面的函数,g1 对应的函数,然后遇到 time.sleep(0) patch 后的 gevent.sleep(0),切换到 g2 对应的函数,并运行,直到遇到 gevent.sleep(0)再次切换。
g2.join()
g3.join()

join() 堵塞,直到调用 join 的对象的完成操作。joinall() 接受一个列表参数。

简单总结

  1. 进程是资源分配的单位
  2. 线程是操作系统调度的单位
  3. 进程切换需要的资源很最大,效率很低 (一般不用)
  4. 线程切换需要的资源一般,效率一般(当然了在不考虑 GIL 的情况下)
  5. 涉及网络堵塞时,优先使用协程, 其切换任务资源很小,效率高
  6. 多进程、多线程根据 cpu 核数不一样可能是并行的,但是协程是在一个线程中所以是并发