網(wǎng)站首頁 編程語言 正文
協(xié)程中未處理的異常會(huì)向上冒泡,傳給 next 函數(shù)或 send 方法的調(diào)用方(即觸發(fā)協(xié)程的對(duì) 象)。
下面示例舉例說明如何使用之前博客示例中由裝飾器定義的 averager 協(xié)程。
未處理的異常會(huì)導(dǎo)致協(xié)程終止
"""
預(yù)激協(xié)程的裝飾器
"""
from inspect import getgeneratorstate
from functools import wraps
def coroutine(func):
? ? """裝飾器:向前執(zhí)行到第一個(gè)`yield`表達(dá)式,預(yù)激`func`"""
? ? # 把被裝飾的生成器函數(shù)替換成這里的 primer 函數(shù);
? ? # 調(diào)用 primer 函數(shù)時(shí),返回預(yù)激后的 生成器。
? ? @wraps(func)
? ? def primer(*args, **kwargs):
? ? ? ? # 調(diào)用被裝飾的函數(shù),獲取生成器對(duì)象。
? ? ? ? gen = func(*args, **kwargs)
? ? ? ? # 預(yù)激生成器。
? ? ? ? next(gen)
? ? ? ? # 返回生成器。
? ? ? ? return gen
? ? return primer
@coroutine
def averager():
? ? total = 0.0
? ? count = 0
? ? average = None
? ? while True:
? ? ? ? term = yield average
? ? ? ? total += term
? ? ? ? count += 1
? ? ? ? average = total / count
if __name__ == '__main__':
? ? coro_avg = averager()
? ? # print(getgeneratorstate(coro_avg))
? ? print(coro_avg.send(10))
? ? print(coro_avg.send(30))
? ? # 發(fā)送的值不是數(shù)字,導(dǎo)致協(xié)程內(nèi)部有異常拋出。
? ? print(coro_avg.send('spam'))
? ? # 由于在協(xié)程內(nèi)沒有處理異常,協(xié)程會(huì)終止。
? ? # 如果試圖重新激活協(xié)程,會(huì)拋出 StopIteration 異常。
? ? print(coro_avg.send(60))
上面示例,暗示了終止協(xié)程的一種方式:發(fā)送某個(gè)哨符值,讓協(xié)程退出。內(nèi)置的 None 和 Ellipsis 等常量經(jīng)常用作哨符值。Ellipsis 的優(yōu)點(diǎn)是,數(shù)據(jù)流中不太常有這個(gè)值。我還見 過有人把 StopIteration 類(類本身,而不是實(shí)例,也不拋出)作為哨符值;也就是說, 是像這樣使用的:my_coro.send(StopIteration)。
從 Python 2.5 開始,客戶代碼可以在生成器對(duì)象上調(diào)用兩個(gè)方法,顯式地把異常發(fā)給協(xié)程。
這兩個(gè)方法是 throw 和 close。
generator.throw(exc_type[, exc_value[, traceback]])
致使生成器在暫停的 yield 表達(dá)式處拋出指定的異常。
如果生成器處理了拋出的異常,代碼會(huì)向前執(zhí)行到下一個(gè) yield 表達(dá)式,而產(chǎn)出的值會(huì)成為調(diào)用 generator.throw 方法 得到的返回值。
如果生成器沒有處理拋出的異常,異常會(huì)向上冒泡,傳到調(diào)用方的上下 文中。
generator.close()
致使生成器在暫停的yield 表達(dá)式處拋出GeneratorExit 異常。
如果生成器沒有處 理這個(gè)異常,或者拋出了StopIteration 異常(通常是指運(yùn)行到結(jié)尾),調(diào)用方不會(huì) 報(bào)錯(cuò)。
如果收到GeneratorExit 異常,生成器一定不能產(chǎn)出值,否則解釋器會(huì)拋出 RuntimeError 異常。
生成器拋出的其他異常會(huì)向上冒泡,傳給調(diào)用方。
下面舉例說明
如何使用 close 和 throw 方法控制協(xié)程:
"""
學(xué)習(xí)在協(xié)程中處理異常的測(cè)試代碼
"""
from inspect import getgeneratorstate
class DemoException(Exception):
? ? """為這次演示定義的異常類型。"""
def demo_exc_handling():
? ? print('-> coroutine started')
? ? try:
? ? ? ? while True:
? ? ? ? ? ? try:
? ? ? ? ? ? ? ? x = yield
? ? ? ? ? ? # ?特別處理 DemoException 異常
? ? ? ? ? ? except DemoException:
? ? ? ? ? ? ? ? print('*** DemoException handled. Continuing...')
? ? ? ? ? ? # 如果沒有異常,那么顯示接收到的值。
? ? ? ? ? ? else:
? ? ? ? ? ? ? ? print('-> coroutine received: {!r}'.format(x))
? ? finally:
? ? ? ? # 如果不管協(xié)程如何結(jié)束都想做些清理工作,
? ? ? ? # 要把協(xié)程定義體中相關(guān)的代碼放入try/ finally 塊中
? ? ? ? print('-> coroutine ending')
if __name__ == '__main__':
? ? exc_coro = demo_exc_handling()
? ? next(exc_coro)
? ? exc_coro.send(11)
? ? exc_coro.send(22)
? ? # 激活和關(guān)閉 demo_exc_handling,沒有異常
? ? # exc_coro.close()
? ? # 如果把 DemoException 異常傳入 demo_exc_handling 協(xié)程,
? ? # 它會(huì)處理,然后繼續(xù)運(yùn)行
? ? # exc_coro.throw(DemoException)
? ? # exc_coro.send(33)
? ? # 如果無法處理傳入的異常,協(xié)程會(huì)終止
? ? exc_coro.throw(ZeroDivisionError)
? ? print(getgeneratorstate(exc_coro))
總結(jié)
原文鏈接:https://blog.csdn.net/MZP_man/article/details/100555806
相關(guān)推薦
- 2023-03-27 react使用.env文件管理全局變量的方法_React
- 2022-05-08 react實(shí)現(xiàn)簡單的拖拽功能_React
- 2022-07-02 less與sass(scss)的區(qū)別
- 2022-05-16 通過T-SQL語句創(chuàng)建游標(biāo)與實(shí)現(xiàn)數(shù)據(jù)庫加解密功能_MsSql
- 2022-08-06 Python中if?__name__==‘__main__‘用法詳情_python
- 2022-07-04 Python中字典的緩存池_python
- 2022-06-16 golang?gorm錯(cuò)誤處理事務(wù)以及日志用法示例_Golang
- 2022-05-29 一起來看看C語言的預(yù)處理注意點(diǎn)_C 語言
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支