在协程close()上运行代码 [英] Run code on coroutine close()

查看:55
本文介绍了在协程close()上运行代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写大量使用协程的代码,并且我希望关闭时具有可靠的行为.

I am writing code that uses coroutines heavily, and I want reliable behavior on shutdown.

说我有一个协程和一个上下文管理器:

Say I have a coroutine and a context manager:

from contextlib import contextmanager

@contextmanager
def print_context_manager(text):
    print("Enter", text)
    yield
    print("Exit", text)

def coro():
    with print_context_manager("coro"):
        while True:
            print("Loop", (yield))

我可以这样使用它:

c = coro()
next(c)
c.send("Hello ")
c.send("World!")
c.close()

不幸的是,据我所知,无法在 c.close()上执行自己的代码.尤其是协程中的上下文管理器从不打印"Exit coro"

Unfortunately, as far as I can tell, there is no way to execute my own code on c.close(). In particular the context manager in coroutine never prints "Exit coro"

协程中上下文管理器的意义是什么?我是否必须手动提出一种信号流结束的信号?那么 close()有什么意义呢?

What's the point of context managers in coroutines? Do I have to manually come up with a way to signal the end of a stream? What's the point of close() then?

请参见以下示例: https://repl.it/M0XI/0

推荐答案

您的上下文管理器存在错误.对其进行更正,当协程关闭时,它将自动执行清理.

Your context manager has a bug. Correct it, and it will automatically perform cleanup when the coroutine is closed.

关闭协程的工作原理是在协程暂停的位置升高 GeneratorExit .如果 with 中的代码引发异常,则 @ contextlib.contextmanager 会在 yield 时引发该异常.您的上下文管理器不会处理此问题,因此该异常会阻止运行清理.

Closing a coroutine works by raising GeneratorExit at the point where the coroutine is suspended. If the code in the with raises an exception, @contextlib.contextmanager raises that exception at the point of the yield. Your context manager doesn't deal with that, so the exception prevents the cleanup from running.

如果您希望即使在异常情况下也要运行清除,则需要将 yield 包装在try-finally中,并在 finally 中进行清理:

You need to wrap the yield in a try-finally and do cleanup in the finally if you want the cleanup to run even on an exception:

@contextmanager
def print_context_manager(text):
    print("Enter", text)
    try:
        yield
    finally:
        print("Exit", text)

这篇关于在协程close()上运行代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆