【问题标题】:Resuming generator after handling exception outside在外部处理异常后恢复生成器
【发布时间】:2022-01-01 21:31:08
【问题描述】:

我有一个处理数据的生成器,但可能会抛出异常。这个异常需要在生成器之外处理,但我想在之后恢复生成器。一个简单的例子:

def generator():
    yield "some data"
    raise ValueError("Something bad happened")
    yield "more data"


def use_generator():
    gen = generator()
    while True:
        try:
            thing = next(gen)
            do_something(thing)
        except ValueError:
            handle_error()
        except StopIteration:
            break

def do_something(thing):print(thing)
def handle_error():print("caught ValueError") 

预期的输出类似于

一些数据

捕获值错误

更多数据

这样不行,因为抛出异常后,对生成器的任何调用都只会引发一个StopIteration,所以异常后就不能使用生成器了。外部处理异常后有没有办法恢复功能?

一种方法是在生成器中捕获错误(我确实知道预期的错误位置和类型)并产生它。修改后会是这样的:

def generator2():
    yield "some data"
    try:
        raise ValueError("Something bad happnened")
    except ValueError as e:
        yield e
    yield "more data"

def use_generator2():
    gen = generator2()
    while True:
        try:
            thing = next(gen)

            if isinstance(thing, ValueError):
                raise ValueError

            do_something(thing)
        except ValueError:
            handle_error()
        except StopIteration:
            break

这个版本产生了预期的行为,虽然它也相当麻烦。有没有更好的做事方式?

【问题讨论】:

    标签: python exception generator


    【解决方案1】:
    def generator():
        yield "some data"
        yield "something bad happened"
        yield "more data"
    
    def use_generator(g):
        data = next(g)
        print(data)
        if data == "something bad happened":
            raise ValueError("something bad happened")
        return g
    
    
    def run(g):
        while True:
            try:
                use_generator(g)
            except ValueError:
                print("caught ValueError") 
                g = use_generator(g)
            except StopIteration:
                print("end of iteration")        
                break
            
    
    if __name__ == '__main__':
        g = use_generator(generator())
        run(g)
    

    解释:

    1. 生成器函数仅生成数据
    2. use_generator 函数使用生成器并引发由 main 函数运行捕获的错误。如果生成器引发错误,则只有在您进一步传递错误时才会被 use_generator 函数看到。
    3. run 函数是执行逻辑的主要函数。 main 函数在生成器耗尽时引发了 StopIteration,并且处理了由 use_generator 函数引发的 ValueError。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-10
      • 2013-11-20
      • 1970-01-01
      • 2013-12-19
      • 2013-04-05
      • 2012-07-07
      • 2012-07-07
      相关资源
      最近更新 更多