(20)gevent协程

协程: 也叫纤程,协程是线程的一种实现,指的是一条线程能够在多任务之间来回切换的一

种实现,对于CPU、操作系统来说,协程并不存在

任务之间的切换会花费时间.目前电脑配置一般线程开到200会阻塞卡顿 .

协程的实现: 协程帮助你记住哪个任务执行到哪个位置上了,并且实现安全的切换

一个任务一旦阻塞卡顿,立刻切换到另一个任务继续执行,保证线程总是忙碌的,更加充

分的利用,

CPU,抢占更多的时间片

一个线程可以由多个协程来实现,协程之间不会产生数据安全问题

协程模块:

greenlet gevent的底层,协程,切换的模块

gevent 直接用的,gevent能提供更全面的功能

(1) 用生成器写生产者消费者模型

def producer():

for i in range(100):

yield i

def consumer():

g = producer() # g 就是一个生成器

for num in g:

print(num)

consumer()

(2) 普通版 greenlet+switch组合 基本实现,只能进行手动切换,

缺陷:不能规避雕io,不能自动实现遇到阻塞就切换.

from greenlet import greenlet

import time

def eat():

print("eat one1")

# 切换到play这个协程中

g2.switch()

time.sleep(1)

print("eat one2")

def play():

print("play one1")

print("play one2")

g1.switch()

g1 = greenlet(eat)

g2 = greenlet(play)

g1.switch()

(3) 升级版 gevent+spawn组合 有缺陷,不能够识别time.sleep()

spawn 自动检测阻塞,遇到阻塞就切换,相当于switch 的升级版 ,

import gevent,time

def eat():

print("eat one1")

time.sleep(1)

print("eat one2")

def play():

print("play one1")

time.sleep(1)

print("play one2")

g1 = gevent.spawn(eat)

g2 = gevent.spawn(play)

# 协程的阻塞也是join

g1.join() # 阻塞直到g1协程执行完毕

g2.join() # 阻塞直到g2协程执行完毕

(4) 进阶版本 用gevent.sleep() 取代time.sleep()

import gevent,time

spawn 自动检测阻塞,遇到阻塞就切换

相当于switch 的升级版 ,

瑕疵:不能够识别time.sleep() 有些阻塞不认识.

def eat():

print("eat one1")

gevent.sleep(1)

print("eat one2")

def play():

print("play one1")

gevent.sleep(1)

print("play one2")

g1 = gevent.spawn(eat)

g2 = gevent.spawn(play)

# 协程的阻塞也是join

g1.join() # 阻塞直到g1协程执行完毕

g2.join() # 阻塞直到g2协程执行完毕

(5) 终极解决办法 gevent+spawn +monkey.patch_all()

# 简化:都写在一行的情况下,有分号隔开.

from gevent import monkey;monkey.patch_all()

import time ,gevent

def eat():

print("eat one1")

time.sleep(1)

print("eat one2")

def play():

print("play one1")

time.sleep(1)

print("play one2")

g1 = gevent.spawn(eat)

g2 = gevent.spawn(play)

# 协程的阻塞也是join

g1.join() # 阻塞直到g1协程执行完毕

g2.join() # 阻塞直到g2协程执行完毕

 

 

上一篇:Python抓取大型网站JS特效模板,想要的资源都能爬!


下一篇:如何让kafka-python或pykafka作为uwsgi和gevent的异步生产者工作?