运行 协程 close() 代码
Run code on coroutine close()
我正在编写大量使用协程的代码,我希望在关闭时有可靠的行为。
假设我有一个协程和一个上下文管理器:
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"
协程中的上下文管理器有什么意义?我是否必须手动想出一种方法来表示流结束?那close()
有什么意义呢?
看这个例子:https://repl.it/M0XI/0
您的上下文管理器有错误。更正一下,协程关闭时会自动进行清理。
关闭协程是通过在协程被挂起的地方引发 GeneratorExit
来实现的。如果 with
中的代码引发异常,则 @contextlib.contextmanager
会在 yield
处引发该异常。您的上下文管理器不处理该问题,因此异常会阻止 运行ning.
进行清理
您需要将 yield
包装在 try-finally 中,并在 finally
中进行清理,如果您希望清理到 运行,即使出现异常也是如此:
@contextmanager
def print_context_manager(text):
print("Enter", text)
try:
yield
finally:
print("Exit", text)
我正在编写大量使用协程的代码,我希望在关闭时有可靠的行为。
假设我有一个协程和一个上下文管理器:
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"
协程中的上下文管理器有什么意义?我是否必须手动想出一种方法来表示流结束?那close()
有什么意义呢?
看这个例子:https://repl.it/M0XI/0
您的上下文管理器有错误。更正一下,协程关闭时会自动进行清理。
关闭协程是通过在协程被挂起的地方引发 GeneratorExit
来实现的。如果 with
中的代码引发异常,则 @contextlib.contextmanager
会在 yield
处引发该异常。您的上下文管理器不处理该问题,因此异常会阻止 运行ning.
您需要将 yield
包装在 try-finally 中,并在 finally
中进行清理,如果您希望清理到 运行,即使出现异常也是如此:
@contextmanager
def print_context_manager(text):
print("Enter", text)
try:
yield
finally:
print("Exit", text)