#协程介绍及基本示例

  

 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
#greenlet #Gevent 的安装
1 pip install wheel
2 
3 pip install gevent
JetBrains PyCharm 5.0.3
 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 ])
#greenlet 已经封装好的协程 #Gevent
  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)
Vi#协程gevent并发爬网页
原文地址:https://www.cnblogs.com/ujq3/p/7350186.html