python之路(15)协程(yield)
前言
线程和进程都是抢占式是使用cpu资源,协程是非抢占式的使用cpu资源,可以认为的去指定程序去使用cpu资源。协程不通过线程而实现程序的并发。但是协程只能在一个进程中执行,无法使用多核,因此多进程+协程是一种很好的方案
通过使用yield来模拟线程间切换数据的保存
#这是一个生成器 def consumer(name): print("--->ready to eat baozi...") while True: new_baozi = yield print("[%s] is eating baozi %s" % (name,new_baozi)) #time.sleep(1) def producer(): r = con.__next__() #consumer对象在yield处挂住,等待传值赋值给new_baozi r = con2.__next__() #consumer对象在yield处挂住,等待传值赋值给new_baozi n = 0 while 1: time.sleep(1) print("\033[32;1m[producer]\033[0m is making baozi %s and %s" %(n,n+1) ) con.send(n) #发送数据给yield,将值赋值给new_baozi con2.send(n+1) #发送数据给yield,将值赋值给new_baozi n +=2 if __name__ == '__main__': con = consumer("c1") con2 = consumer("c2") producer() ############################### --->ready to eat baozi... --->ready to eat baozi... [producer] is making baozi 0 and 1 [c1] is eating baozi 0 [c2] is eating baozi 1 [producer] is making baozi 2 and 3 [c1] is eating baozi 2 [c2] is eating baozi 3 [producer] is making baozi 4 and 5 [c1] is eating baozi 4 [c2] is eating baozi 5 [producer] is making baozi 6 and 7 [c1] is eating baozi 6 [c2] is eating baozi 7 ......
greenlet模块
from greenlet import greenlet def test1(): print(12) gr2.switch() #切换到test2()处 print(34) def test2(): print(56) gr1.switch() #切换到test1()处 print(78) gr1.switch() #切换到test1()处 gr1 = greenlet(test1) gr2 = greenlet(test2) gr2.switch() #切换到test2()处 ################### 56 12 78 34
gevent模块
import gevent import requests,time def f(url): print('GET: %s' % url) resp =requests.get(url) #爬取网站 data = resp.text print('%d bytes received from %s.' % (len(data), url)) #5个爬取操作进行协程的操作 gevent.joinall([ gevent.spawn(f, 'https://www.python.org/'), #f是函数名,后面是参数 gevent.spawn(f, 'https://www.yahoo.com/'), gevent.spawn(f, 'https://www.baidu.com/'), gevent.spawn(f, 'https://www.sina.com.cn/'), gevent.spawn(f, 'http://www.xiaohuar.com/hua/'), ])
通过协程的方式进行爬取网站要比串行的方式进行爬取网站要快,爬取的内容越多,差别越大