协程简介
区别:线程和进程的操作是由程序触发系统接口,执行者是系统;协程的操作则是程序员。
协程存在的意义:对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时(保存状态,下次继续)。协程,则只使用一个线程,在一个线程中规定某个代码块执行顺序。
协成的原理:利用一个线程,分解一个线程成为多个微线程,注意此时从程序级别来分解的
适用场景:当程序中存在大量不需要CPU的操作时(IO),适用于协程;
实现技术
需要手动安装 greenlet模块 和 gevent模块。安装gevent模块会默认安装greenlet模块
基于底层greenlet实现
1 from greenlet import greenlet 2 3 def test1(): 4 print(1,2) # 2.执行输出语句,输出1,2 5 gr2.switch() # 3.执行完上面输出语句后,此行调用test2函数 6 print(3,4) # 6.执行输出语句,输出3,4 7 gr2.switch() # 7.执行完上面输出语句后,此处调用test2函数 8 9 def test2(): 10 print(5,6) # 4.执行输出语句,输出5,6 11 gr1.switch() # 5.执行完上面输出语句后,此行调用test1函数 12 print(7,8) # 8.执行输出语句,输出7,8 13 14 gr1 = greenlet(test1) # 1.调用grl1对应的test1函数 15 gr2 = greenlet(test2) 16 gr1.switch()

1 1,2 2 5,6 3 3,4 4 7,8
基于底层gevent实现
1 import gevent
2
3 def foo():
4 print('Running in foo')
5 gevent.sleep(0)
6 print('Explicit context switch to foo again')
7
8 def bar():
9 print('Explicit context to bar')
10 gevent.sleep(0)
11 print('Implicit context switch back to bar')
12
13 gevent.joinall([
14 gevent.spawn(foo),
15 gevent.spawn(bar),
16 ])

1 Running in foo 2 Explicit context to bar 3 Explicit context switch to foo again 4 Implicit context switch back to bar
实例
1 from gevent import monkey; monkey.patch_all()
2 import gevent
3 import requests
4
5 def f(url):
6 print('GET: %s' % url)
7 resp = requests.get(url)
8 data = resp.text
9 print('%d bytes received from %s.' % (len(data), url))
10
11 gevent.joinall([
12 gevent.spawn(f, 'https://www.python.org/'),
13 gevent.spawn(f, 'https://www.yahoo.com/'),
14 gevent.spawn(f, 'https://github.com/'),
15 ])

1 GET: https://www.python.org/ 2 GET: https://www.yahoo.com/ 3 GET: https://github.com/ 4 431218 bytes received from https://www.yahoo.com/. 5 25529 bytes received from https://github.com/. 6 47394 bytes received from https://www.python.org/.
