在协程close()上运行代码 [英] Run code on coroutine 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屋!