1 #协程介绍及基本示例 2 3 #Gevent协程(单线程,串行)在线程里启动 4 ''' 5 协程,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程: 6 协程是一种用户态的轻量级线程。 7 8 协程拥有自己的寄存器上下文和栈。协程调度切换时, 9 将寄存器上下文和栈保存到其他地方,在切回来的时候, 10 恢复先前保存的寄存器上下文和栈。因此: 11 12 协程能保留上一次调用时的状态(即所有局部状态的一个特定组合), 13 每次过程重入时,就相当于进入上一次调用的状态,换种说法: 14 进入上一次离开时所处逻辑流的位置。 15 16 协程的好处: 17 18 1无需线程上下文切换的开销 19 20 2无需原子操作锁定及同步的开销 21 "原子操作(atomic operation)是不需要synchronized", 22 所谓原子操作是指不会被线程调度机制打断的操作; 23 这种操作一旦开始,就一直运行到结束, 24 中间不会有任何 context switch (切换到另一个线程)。 25 原子操作可以是一个步骤,也可以是多个操作步骤, 26 但是其顺序是不可以被打乱,或者切割掉只执行部分。 27 视作整体是原子性的核心。 28 29 3方便切换控制流,简化编程模型 30 31 4高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。 32 所以很适合用于高并发处理。 33 34 35 缺点: 36 37 1无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上, 38 协程需要和进程配合才能运行在多CPU上. 39 当然我们日常所编写的绝大部分应用都没有这个必要, 40 除非是cpu密集型应用。 41 42 2进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序 43 44 45 ''' 46 ''' 47 #使用yield实现协程操作例子 48 49 import time 50 import queue 51 def consumer(name): 52 print("--->starting eating baozi...") 53 while True: 54 new_baozi = yield #返回,唤醒接收数据 55 print("[%s] is eating baozi %s" % (name,new_baozi)) 56 #time.sleep(1) 57 58 def producer(): 59 60 r = con.__next__() 61 r = con2.__next__() 62 n = 0 63 while n < 5: 64 n +=1 65 con.send(n)#send 的作用唤醒传递数据yield 66 con2.send(n) 67 print("1m[producer] is making baozi %s" %n ) 68 69 70 if __name__ == '__main__': 71 con = consumer("c1") 72 con2 = consumer("c2") 73 p = producer() 74 75 ''' 76 ''' 77 #举例 78 import time 79 def home(): 80 print('in func 1') 81 time.sleep(5) 82 print('home exec done') 83 84 def bbs(): 85 print('in func 2') 86 time.sleep(2) 87 '''
1 #greenlet #Gevent 的安装 2 3 环境:python 3.6 win 32位 4 5 python下如何安装.whl包? 6 7 下载.whl包 8 先pip install wheel 9 10 之后pip install 包名字.whl 即可安装某模块包 11 12 13 到哪找.whl文件? 14 http://www.lfd.uci.edu/~gohlke/pythonlibs/ 15 16 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17 https://pypi.python.org/pypi 18 19 https://pypi.python.org/packages/da/78/fbb6d73cf5bc46cc71d2288760afe8ef53beec7850739b61c0d291c1e223/gevent-1.2.2-cp36-cp36m-win32.whl#md5=676cb41e5d265115dae16a969e595882 20 21 https://pypi.python.org/packages/c0/95/49c52a5c354f4115d290cd1210bf71c5aa24481e548ab5a4684a894184fa/greenlet-0.4.12-cp36-cp36m-win32.whl#md5=98b77ae90aa6bc253cf2180a5d807ba9 22 23 24 感谢前面的大神铺垫,我总结一下几个注意点: 25 1.先安装PIP 26 2.CMD命令进入C:Python34Scripts里面后再执行PIP命令安装pip install wheel 27 3.把文件最好放在Script文件夹里面再pip install xxxx.whl 28 4.注意whl文件名不能改 必须一模一样和原名 29 30 31 cd C:UsersAdministratorAppDataLocalProgramsPythonPython36-32Scripts 32 33 pip install wheel 34 35 pip install gevent-1.2.2-cp36-cp36m-win32.whl
1 pip install wheel 2 3 pip install gevent
1 #greenlet 已经封装好的协程 #Gevent 2 #io操作就切换 3 4 ''' 5 greenlet是一个用C实现的协程模块, 6 相比与python自带的yield,它可以使你在任意函数之间随意切换, 7 而不需把这个函数先声明为generator 8 9 ''' 10 ''' 11 # -*- coding:utf-8 -*- 12 from greenlet import greenlet 13 14 15 def test1(): 16 print(12) 17 gr2.switch() 18 print(34) 19 gr2.switch() 20 21 22 def test2(): 23 print(56) 24 gr1.switch() 25 print(78) 26 27 28 gr1 = greenlet(test1)#启动一个协程 29 gr2 = greenlet(test2) 30 gr1.switch() 31 ''' 32 33 34 #Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程, 35 # 在gevent中用到的主要模式是Greenlet, 36 # 它是以C扩展模块形式接入Python的轻量级协程。 37 # Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。 38 import gevent 39 #遇到IO就切换,实现并行效果 40 def foo(): 41 print('running in foo') 42 gevent.sleep(2) 43 print('Explicit context switch tofoo again') 44 45 def bar(): 46 print( 'Explicit 精确的 context 内容 to bar') 47 gevent.sleep(1) 48 print('Explicit context switch back to bar') 49 def func3(): 50 print('running func3') 51 gevent.sleep(0) 52 print('running func3 again') 53 54 gevent.joinall([ 55 gevent.spawn(foo), 56 gevent.spawn(bar), 57 gevent.spawn(func3), 58 ])
1 #协程gevent并发爬网页 2 ''' 3 from urllib import request 4 def f(url): 5 print('GET: %s'% url) 6 resp = request.urlopen(url) 7 data = resp.read() 8 f = open('url.html','wb') 9 f.write(data) 10 f.close() 11 print('%d bytes received from %s'%(len(data),url)) 12 13 f('https://www.baidu.com') 14 15 ''' 16 17 """ 18 from gevent import monkey; monkey.patch_all() 19 import gevent 20 from urllib.request import urlopen 21 22 def f(url): 23 print('GET: %s' % url) 24 resp = urlopen(url) 25 data = resp.read() 26 print('%d bytes received from %s.' % (len(data), url)) 27 28 gevent.joinall([ 29 gevent.spawn(f, 'https://www.python.org/'), 30 gevent.spawn(f, 'https://www.yahoo.com/'), 31 gevent.spawn(f, 'https://github.com/'), 32 ]) 33 """ 34 35 ''' 36 from urllib import request 37 import gevent 38 39 def f(url): 40 print('GET: %s'% url) 41 resp = request.urlopen(url) 42 data = resp.read() 43 print('%d bytes received from %s.' % (len(data), url)) 44 45 gevent.joinall([ 46 gevent.spawn( f, 'https://www.python.org/'), 47 gevent.spawn( f, 'https://www.yahoo.com/'), 48 gevent.spawn( f, 'https://github.com/'), 49 ]) 50 ''' 51 ''' 52 #同步 串行 53 from urllib import request 54 import gevent 55 import time 56 def f(url): 57 print('GET: %s'% url) 58 resp = request.urlopen(url) 59 data = resp.read() 60 print('%d bytes received from %s.' % (len(data), url)) 61 62 urls = [ 63 'https://www.python.org/' , 64 'https://www.yahoo.com/' , 65 'https://www.baidu.com/' 66 ] 67 68 time_start = time.time() 69 for url in urls: 70 f(url) 71 print('同步cost',time.time() - time_start) 72 ''' 73 74 ''' 75 #异步 串行 76 from urllib import request 77 import gevent,time 78 79 def f(url): 80 print('GET: %s'% url) 81 resp = request.urlopen(url) 82 data = resp.read() 83 print('%d bytes received from %s.' % (len(data), url)) 84 85 urls = [ 86 'https://www.python.org/' , 87 'https://www.yahoo.com/' , 88 'https://www.baidu.com/' 89 ] 90 time_start = time.time() 91 for url in urls: 92 f(url) 93 print('同步cost',time.time() - time_start) 94 95 async_time_start = time.time() 96 gevent.joinall([ 97 gevent.spawn( f, 'https://www.python.org/'), 98 gevent.spawn( f, 'https://www.yahoo.com/'), 99 gevent.spawn( f, 'https://github.com/'), 100 ]) 101 102 print('异步cost',time.time() - async_time_start) 103 ''' 104 105 #异步 串行 补丁 monkey 106 #多测试几次才能看清楚 (网速会影响结果) 107 from urllib import request 108 import gevent,time 109 from gevent import monkey 110 111 monkey.patch_all()#把当前程序的所有的IO操作给我单独的做上标记 112 113 def f(url): 114 print('GET: %s'% url) 115 resp = request.urlopen(url) 116 data = resp.read() 117 print('%d bytes received from %s.' % (len(data), url)) 118 119 urls = [ 120 'https://www.python.org/' , 121 'https://www.yahoo.com/' , 122 'https://www.baidu.com/' 123 ] 124 time_start = time.time() 125 for url in urls: 126 f(url) 127 print('同步cost',time.time() - time_start) 128 129 async_time_start = time.time() 130 gevent.joinall([ 131 gevent.spawn( f, 'https://www.python.org/'), 132 gevent.spawn( f, 'https://www.yahoo.com/'), 133 gevent.spawn( f, 'https://github.com/'), 134 ]) 135 136 print('异步cost',time.time() - async_time_start)