Python装饰器无法捕获被装饰生成器函数内部异常问题咨询
结论
你的理解完全正确,当前异常未被捕获就是生成器函数的执行特性导致的。
核心原理说明
只要函数体内包含yield关键字,Python就会将其标记为生成器函数,调用生成器函数时会直接返回生成器迭代器对象,不会执行函数体内的任何代码,你代码里的check(number)逻辑要等到第一次对返回的生成器执行迭代操作时才会运行:
- 你直接调用
dec_mthd_b(1)时,装饰器内的try块仅执行了「创建生成器对象」的逻辑,没有运行check方法,自然不会触发异常,所以不会进入except捕获分支 - 你可以手动验证该逻辑:先执行
gen = dec_mthd_b(1)拿到生成器对象,再执行next(gen)触发迭代,这时候check方法就会运行,异常也会被抛出
你提到的文档中「挂起保留所有异常处理状态」的描述,是指生成器运行到yield暂停时,当前所有的上下文(包括异常处理的作用域、本地变量、执行指针等)都会被保存,下次恢复执行时上下文不会丢失,和你当前遇到的问题逻辑并不冲突。
适配生成器的装饰器修改方案
你当前的装饰器仅包裹了「生成器创建」的流程,要捕获生成器迭代运行时的异常,需要修改装饰器逻辑,将异常捕获包裹在迭代流程中,参考实现如下:
def remediation_decorator(dec_mthd): def new_func(*args, **kwargs): # 先获取原生成器对象 origin_gen = dec_mthd(*args, **kwargs) try: # 驱动原生成器运行,捕获执行过程中抛出的异常 yield from origin_gen except (KeyError, HTTPError) as err: print(f'error = {err}... call the remediation function') return new_func
修改后你可以通过list(dec_mthd_b(1))触发迭代,即可看到异常被成功捕获的输出。
内容的提问来源于stack exchange,提问作者hitzoglin
相关产品推荐
相关产品推荐

