协程,yield下支持的协程,gevent下支持的协程,简单爬虫注:协程程序运行时间取决于其最长协程的执行时间协程:又称微线程,线程。英文名Coroutine。协程是一种用户态的轻量级线程。协程拥有本身的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其它地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。所以:协程能保留上一次调用时的状态(即全部局部状态的一个特定组成),每次过程重入时,就至关于进入上一次调用时的状态,换种说法:进入上一次离开时所在逻辑流的位置。协程的好处:(1)无需线程上下文切换的开销(2)无需原子操做锁定即同步的开销(3)方便切换控制流,简化线程模型(4)高并发+高扩展+低成本:一个cpu支持上万的协程都不是问题。因此很适合用于高并发处理。缺点:(1)没法利用多核资源:协程的本质是个单线程,他不能同时将单个cpu的多个核用上,协程须要和进程配合才能运行在多 cpu上,平常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。(2)进行阻塞(Blocking)操做(如IO时)会阻塞掉整个程序。1.yield下支持的协程: (1) import time import queue def consumer(name): print(" ") while True: new_baozi = yield print("[%s] is eating baozi %s"%(name,new_baozi)) def producer(): r = con.__next__() r = con2.__next__() n=0 while n<5: n += 1 con.send(n) con2.send(n) print("is making baozi %s"%n) if __name__=='__main__': con = consumer("c1") con2 = consumer("c2") p=producer() (2) def f(): print('ok1') count=yield 5 print(count) print('ok2') yield 6 # print(f())#<generator object f at 0x00000164C3A8F4F8> gen=f() # ret=next(gen)#生成器 # print(ret) ret = gen.send(None)#注:第一次send的时候是找不到目标的,要有一次yield折回 print(ret) x=gen.send(8) print(x)2.gevent下支持的协程: #author: wylkjj #date:2019/5/13 from greenlet import greenlet def test1(): print(12) gr2.switch()#切换 print(34) gr2.switch()#切换 def test2(): print(56) gr1.switch()#切换 print(78) gr1 = greenlet(test1)#建立对象 # print(gr1) gr2 = greenlet(test2)#建立对象 gr1.switch()#调用执行 结果:12 56 34 78 简单协程实例: import gevent def foo(): print('Running in foo') gevent.sleep(0)#模拟IO阻塞 print('Explicit context switch to foo again') def bar(): print('Explicit context to bar') gevent.sleep(0)#模拟IO阻塞 print('Implicit switch back bar') gevent.joinall([ gevent.spawn(foo), gevent.spawn(bar), ])3.简单爬虫: (1)爬取网页并写到文件里面 from urllib.request import urlopen def f(url): print('GET:%s'%url) resp = urlopen(url) data = resp.read() with open('bilibili.html','wb')as f: f.write(data) print('%d bytes received from %s.'%(len(data),url)) f('https://www.bilibili.com/') (2)爬取网页 #author: wylkjj #date:2019/5/14 import gevent,time from gevent import monkey #对IO流监控增强控制 monkey.patch_all() from urllib.request import urlopen def f(url): print('GET:%s'%url) resp = urlopen(url) data = resp.read() # with open('bilibili.html','wb')as f: # f.write(data) print('%d bytes received from %s.'%(len(data),url)) # f('https://www.bilibili.com/') # list = ['https://www.python.org/','https://www.yahoo.com/','https://github.com/'] start=time.time() # for url in list: # f(url)#8.78313660621643秒 gevent.joinall([ #时间3.7336878776550293秒 协程节省时间 gevent.spawn(f,'https://www.python.org/'), gevent.spawn(f,'https://www.yahoo.com/'), gevent.spawn(f,'https://github.com/'), ]) print(time.time()-start)