python协程笔记
一、协程
协程 是为非抢占式多任务产生子程序的计算机程序组件,协程允许不同入口点在不同位置暂停或开始执行程序
可以看做一个可以暂停的函数以及一个生成器
二、协程常用包
asyncio,tornado,gevent
三、协程的实现
yield返回
send调用
四、协程的四种状态
inspect.getgeneratorstate(...)函数确认,该函数会返回下面字符中的一:
GEN_CREATER:等待开始执行
GEN_RUNNING:解释器正在执行
GEN_SUSPENED:在yield表达式处暂停
GEN_CLOSED:执行结束
next预激(prime)
案例1
1 def My_Coroutines(): 2 print('-->start') 3 x = yield 4 print('x is %s' % x) 5 print('-->end') 6 7 g = My_Coroutines() 8 next(g) 9 10 g.send('Q')
-->start x is Q -->end --------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-1-dfd01338da14> in <module>() 8 next(g) 9 ---> 10 g.send('Q') StopIteration:
预激:
next(t) 或者 t.seed(None)
该程序会在程序结束后抛出StopIteration异常,因为在send将信号Q发送到原函数执行完毕后,在函数中找不到下一个yield,又返回到send抛出异常,解决方案可以在结尾加上yield
案例2
1 def My_Coroutines(): 2 print('-->start') 3 x = yield 4 print('x is %s' % x) 5 print('-->end') 6 yield 7 8 g = My_Coroutines() 9 next(g) 10 g.send('Q')
-->start x is Q -->end
协程执行的顺序是:
预激函数(next(g)) --> print('-->start') --> 在yield表达式处暂停 -->预激执行结束 --> 再次调用原函数(g.send('Q')) --> 'Q'传入x --> print('x is %s' % x) --> print('-->end') --> 在yield表达式处暂停 -->程序结束
案例3
1 def My_Coroutines(a): 2 print('-->start') 3 print('a is {0}'.format(a)) 4 b = yield a 5 print('a b is {0} {1}'.format(a,b)) 6 c = yield a + b 7 print('a b c is {0} {1} {2}'.format(a,b,c)) 8 yield a + b + c 9 10 a = My_Coroutines(5) 11 12 q1 = next(a) 13 print(q1) 14 q2 = a.send(3) 15 print(q2) 16 q3 = a.send(1) 17 print(q3)
-->start a is 5 5 a b is 5 3 8 a b c is 5 3 1 9
五、yield from
1.yield from
为了让生成器,能简易的在其他函数中直接调用,就产生了yield from
yield from 就是从其他函数中找到子生成器中的yield
yield from从内部捕获StopIteration异常
六、委派生成器
包含yield from <iterable> 表达式的生成器函数
案例4
出自:https://blog.csdn.net/chenbin520/article/details/78111399?locationNum=7&fps=1
1 def htest(): 2 i = 1 3 while i < 4: 4 n = yield i 5 if i == 3: 6 return 100 7 i += 1 8 9 #委派生成器 10 def itest(): 11 val = yield from htest() 12 print(val) 13 14 t = itest() 15 t.send(None) 16 j = 0 17 while j < 3: 18 j += 1 19 try: 20 t.send(j) 21 except StopIteration as e: 22 print('异常了')
通过
把yield from换成yield
把return换成yield
之类的更改,能够窥到yield from的一思半解
七、asyncio异步