【问题标题】:Run code on coroutine close()在协程 close() 上运行代码
【发布时间】:2023-03-28 11:24:01
【问题描述】:

我正在编写大量使用协程的代码,我希望在关机时有可靠的行为。

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

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

【问题讨论】:

  • "特别是 write_to_file 协程中的文件上下文管理器从不关闭文件。"你确定吗?如果关闭协程没有运行 finally 块并退出上下文管理器,我会感到惊讶。
  • 无论是生成器协程还是新的相似但不同的异步协程,关闭协程运行finally 块和__exit__ 方法。您无需编写自己的处理方式即可。
  • 这里是演示问题的示例:repl.it/M0XI/0。如果你能看出我做错了什么,请告诉我
  • 太棒了! - 让我重做我的问题以包含我的错误代码,你可以用同样的方式回答它。

标签: python python-3.x coroutine


【解决方案1】:

您的上下文管理器有错误。更正一下,协程关闭时会自动进行清理。

关闭协程通过在协程暂停的点引发GeneratorExit 来工作。如果with 中的代码引发异常,则@contextlib.contextmanageryield 处引发该异常。您的上下文管理器不会处理此问题,因此异常会阻止清理运行。

您需要将yield 包装在try-finally 中,并在finally 中进行清理,如果您希望即使出现异常也能运行清理:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-12
    • 2018-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多