【问题标题】:try/except/finally in Coroutine在协程中尝试/除外/最终
【发布时间】:2020-10-13 03:13:55
【问题描述】:
class DemoException(Exception):   
    """An exception type for the demonstration."""

def demo_exc_handling():
    print('-> coroutine started')
    while True:
        try:
            x = yield
        except DemoException:  # <1>
            print('*** DemoException handled. Continuing...')
        else:  # <2>
            print('-> coroutine received: {!r}'.format(x))
        finally:
            print('-> 1111111111coroutine ending')
    raise RuntimeError('This line should never run.')  

if __name__ == '__main__':
exc_coro = demo_exc_handling()
next(exc_coro)
exc_coro.send(11)

我得到以下输出:

-> coroutine started
-> coroutine received: 11
-> 1111111111coroutine ending
-> 1111111111coroutine ending

我想知道finally语句为什么会执行两次? 如果有任何帮助,我将不胜感激。

【问题讨论】:

    标签: python coroutine finally


    【解决方案1】:

    它会打印两次,因为即使主程序结束,finally 子句也会执行。

    主程序结束时协程第二次让步

    让我们生成迭代次数并添加几个打印输出来查看它

    class DemoException(Exception):   
        """An exception type for the demonstration."""
        pass
    
    def demo_exc_handling():
        print('-> coroutine started')
        i = 1
        while True:
            try:
                print(f"iteration {i}")
                x = yield i
            except DemoException:  # <1>
                print('*** DemoException handled. Continuing...')
            else:  # <2>
                print('-> coroutine received: {!r}'.format(x))
            finally:
                print('-> 1111111111coroutine ending')
            i += 1
        raise RuntimeError('This line should never run.')  
    
    if __name__ == '__main__':
        exc_coro = demo_exc_handling()
        print("initialised")
        y = next(exc_coro)
        print(f"got {y}")
        exc_coro.send(11)
    
    

    生产

    initialised
    -> coroutine started
    iteration 1
    got 1
    -> coroutine received: 11
    -> 1111111111coroutine ending
    iteration 2
    -> 1111111111coroutine ending
    

    【讨论】:

    • 感谢您的回答。看完你的回答后,我能不能这样理解:当主程序结束时,协程也将终止。因为协程在 try-except-finally 块中的 yield 中挂起,所以它将执行 finally 子句然后终止。
    【解决方案2】:

    这与协程或异常无关。只需一个生成器就可以很好地重现:

    def demo_exc_handling():
        print('-> coroutine started')
        while True:
            try:
                x = yield
            finally:
                print('-> 1111111111coroutine ending')
        raise RuntimeError('This line should never run.')
    
    if __name__ == '__main__':
        exc_coro = demo_exc_handling()
        next(exc_coro)
        next(exc_coro)
    

    这是输出:

    -> coroutine started
    -> 1111111111coroutine ending
    -> 1111111111coroutine ending
    

    您可能打算在 try-finally 中使用 while 循环:

    def demo_exc_handling():
        print('-> coroutine started')
        try:
            while True:
                x = yield
        finally:
            print('-> 1111111111coroutine ending')
        raise RuntimeError('This line should never run.')
    

    改为输出

    -> coroutine started
    -> 1111111111coroutine ending
    

    【讨论】:

    • 它没有回答问题
    • 是的。作者调换了两个循环的顺序。它执行了两次,因为循环不是作者认为的顺序。 “finally”子句总是在完成“try”时执行,会发生两次。
    • “完成“尝试”时始终执行“最终”子句”对我有帮助。谢谢。
    猜你喜欢
    • 2021-05-17
    • 1970-01-01
    • 2023-03-25
    • 2021-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多