1、停止协程与异常处理
2、协程返回值
协程中未处理的值会向上冒泡,传给next函数或send方法的调用方(即触发协程的对象)
def make_avg():
total = 0
count = 0
avg = None
while True:
term = yield avg
total += term
count += 1
avg = total / count
avg_coro = make_avg()
next(avg_coro)
print(avg_coro.send(5))
avg_coro.send('abc')#发送的不是数字,导致协程内部异常
由于在协程内没有处理异常,协程会终止p y。如果尝试重新激活协程,会抛出StopIteration异常,所以终止协程可以通过发送某个哨符值,让协程退出。
class DemoException(Exception):
pass
def demo_exc_handing():
print('coroutine started')
while True:
try:
x = yield
except DemoException:
print('DemoExcep')
else:
print('coroutine received: ',x)
raise RuntimeError('this line shoule never run')
exc_coro = demo_exc_handing()
next(exc_coro)
exc_coro.send(2)
exc_coro.close()
from inspect import getgeneratorstate
print(getgeneratorstate(exc_coro))#查看状态
exc_coro2 = demo_exc_handing()
next(exc_coro2)
exc_coro2.send(1)
exc_coro2.throw(DemoException)#传入协程可以处理的异常
exc_coro2.throw(ZeroDivisionError)
#协程返回值
from collections import namedtuple
Result = namedtuple('Result','count average')
def make_avg():
total = 0
count = 0
avg = None
while True:
term = yield
#为了返回值,协程必须正常终止
if term is None:
break
total += term
count += 1
avg = total / count
return Result(count,avg)
avg_coro = make_avg()
next(avg_coro)
print(avg_coro.send(10))
print(avg_coro.send(20))
try:
avg_coro.send(None)
except StopIteration as e:
result = e.vaule
print(result)