【问题标题】:Python: best way to use ExitStack to avoid multiple with statementPython:使用 ExitStack 避免多个 with 语句的最佳方法
【发布时间】:2021-03-08 01:41:12
【问题描述】:

我在使用 ExitStack 而不是 with 语句的地方有以下代码。

from contextlib import contextmanager
from contextlib import ExitStack
from tempfile import NamedTemporaryFile


@contextmanager
def myfile():
    temp_file = NamedTemporaryFile(suffix='.txt')
    temp_file.seek(0)
    yield temp_file
    os.unlink(temp_file.name)


with ExitStack() as stack:
    files = []
    for idx in range(5):
        files.append(stack.enter_context(myfile()))
    # do something with the files

上面的代码给出了如下 5 条错误消息

FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmpbupwinzt.txt'

我是否以错误的方式使用 ExitStack。做上述事情的正确方法是什么。

注意:我无法更改myfile() 函数,但我可以更改其余代码。

【问题讨论】:

  • 使用多个with语句是否有效?
  • with myfile() as f1: with myfile() as f2: # do something here 我也得到与多个 with 语句相同的错误。
  • 那么我认为错误不在 ExitStack 中,对吧?

标签: python with-statement contextmanager


【解决方案1】:

我想我找到了解释。来自docs

[A TemporaryFile] 将在关闭后立即销毁(包括隐式 当对象被垃圾回收时关闭)。

但是,您正在取消链接程序中的文件(myfile 的最后一行)。测试程序结束时,垃圾收集无法关闭和取消链接文件并打印错误。换句话说,with 语句中没有发生错误。

一个简单的解决方案是禁用自动删除:

NamedTemporaryFile(suffix='.txt', delete=False)

但是我认为新文件上的seek(0) 是不必要的,整个myfile 没有做任何NamedTemporaryFile 没有做的事情,所以你可以直接使用它:

with ExitStack() as stack:
    files = []
    for idx in range(5):
        files.append(stack.enter_context(NamedTemporaryFile(suffix='.txt')))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-22
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 2015-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多