Python:使用ExitStack避免多个with语句的最佳方法

5

我有以下代码,其中我使用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 语句,它是否有效? - Dani Mesejo
使用with语句时遇到了错误,即使使用多个with语句也是如此。with myfile() as f1: with myfile() as f2: # do something here - asdfkjasdfjk
2
那么我认为错误不在于ExitStack,对吧? - Dani Mesejo
1个回答

1
我想我找到了一个解释。来自文档
临时文件将在关闭时被销毁(包括对象垃圾收集时的隐式关闭)。
但是,在程序中您正在取消链接文件(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')))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接