網站首頁 編程語言 正文
協程中未處理的異常會向上冒泡,傳給 next 函數或 send 方法的調用方(即觸發協程的對 象)。
下面示例舉例說明如何使用之前博客示例中由裝飾器定義的 averager 協程。
未處理的異常會導致協程終止
"""
預激協程的裝飾器
"""
from inspect import getgeneratorstate
from functools import wraps
def coroutine(func):
? ? """裝飾器:向前執行到第一個`yield`表達式,預激`func`"""
? ? # 把被裝飾的生成器函數替換成這里的 primer 函數;
? ? # 調用 primer 函數時,返回預激后的 生成器。
? ? @wraps(func)
? ? def primer(*args, **kwargs):
? ? ? ? # 調用被裝飾的函數,獲取生成器對象。
? ? ? ? gen = func(*args, **kwargs)
? ? ? ? # 預激生成器。
? ? ? ? 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))
? ? # 發送的值不是數字,導致協程內部有異常拋出。
? ? print(coro_avg.send('spam'))
? ? # 由于在協程內沒有處理異常,協程會終止。
? ? # 如果試圖重新激活協程,會拋出 StopIteration 異常。
? ? print(coro_avg.send(60))
上面示例,暗示了終止協程的一種方式:發送某個哨符值,讓協程退出。內置的 None 和 Ellipsis 等常量經常用作哨符值。Ellipsis 的優點是,數據流中不太常有這個值。我還見 過有人把 StopIteration 類(類本身,而不是實例,也不拋出)作為哨符值;也就是說, 是像這樣使用的:my_coro.send(StopIteration)。
從 Python 2.5 開始,客戶代碼可以在生成器對象上調用兩個方法,顯式地把異常發給協程。
這兩個方法是 throw 和 close。
generator.throw(exc_type[, exc_value[, traceback]])
致使生成器在暫停的 yield 表達式處拋出指定的異常。
如果生成器處理了拋出的異常,代碼會向前執行到下一個 yield 表達式,而產出的值會成為調用 generator.throw 方法 得到的返回值。
如果生成器沒有處理拋出的異常,異常會向上冒泡,傳到調用方的上下 文中。
generator.close()
致使生成器在暫停的yield 表達式處拋出GeneratorExit 異常。
如果生成器沒有處 理這個異常,或者拋出了StopIteration 異常(通常是指運行到結尾),調用方不會 報錯。
如果收到GeneratorExit 異常,生成器一定不能產出值,否則解釋器會拋出 RuntimeError 異常。
生成器拋出的其他異常會向上冒泡,傳給調用方。
下面舉例說明
如何使用 close 和 throw 方法控制協程:
"""
學習在協程中處理異常的測試代碼
"""
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:
? ? ? ? # 如果不管協程如何結束都想做些清理工作,
? ? ? ? # 要把協程定義體中相關的代碼放入try/ finally 塊中
? ? ? ? print('-> coroutine ending')
if __name__ == '__main__':
? ? exc_coro = demo_exc_handling()
? ? next(exc_coro)
? ? exc_coro.send(11)
? ? exc_coro.send(22)
? ? # 激活和關閉 demo_exc_handling,沒有異常
? ? # exc_coro.close()
? ? # 如果把 DemoException 異常傳入 demo_exc_handling 協程,
? ? # 它會處理,然后繼續運行
? ? # exc_coro.throw(DemoException)
? ? # exc_coro.send(33)
? ? # 如果無法處理傳入的異常,協程會終止
? ? exc_coro.throw(ZeroDivisionError)
? ? print(getgeneratorstate(exc_coro))
總結
原文鏈接:https://blog.csdn.net/MZP_man/article/details/100555806
相關推薦
- 2022-11-05 swift語言AutoreleasePool原理及使用場景_Swift
- 2022-10-20 VS?Code?常用自定義配置代碼規范保存自動格式化_相關技巧
- 2022-08-03 Go?GORM版本2.0新特性介紹_Golang
- 2022-06-01 Python全角與半角之間相互轉換的方法總結_python
- 2022-10-30 Android?WebView預渲染介紹_Android
- 2022-09-15 Python利用shutil實現拷貝文件功能_python
- 2022-05-23 python中3種等待元素出現的方法總結_python
- 2022-05-20 golang?croncli?定時器命令詳解_Golang
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支