Windows上的NamedTemporaryFile有什么用?

5 投票
4 回答
3936 浏览
提问于 2025-04-16 19:57

Python的一个模块叫做tempfile,里面有两个功能:NamedTemporaryFileTemporaryFile。关于NamedTemporaryFile的说明中提到:

在某些平台上,打开这个命名临时文件的名字是否可以再次使用,取决于具体的平台(在Unix系统上可以这样做;但在Windows NT或更高版本上就不行)。

那这个文件有名字有什么用呢,如果我不能用这个名字?如果我想在Windows上也能像在Unix上一样使用这个名字,我就得复制代码,把所有提到if _os.name == 'nt'之类的部分都删掉。

这是怎么回事呢?这肯定是有用的,因为它是这样设计的,但到底有什么用呢?

4 个回答

1

你不想“把所有的东西都撕掉...”。这样写是有原因的。它的意思是,在文件还打开的时候,你不能再第二次打开它。不要这样做。只用一次,然后扔掉它(毕竟,它是个临时文件)。如果你想要一个永久的文件,就自己创建一个。

“这肯定有什么用,因为它是故意这样编写的,但具体有什么用呢?”嗯,我之前用它来写电子邮件(以二进制格式),然后再把它们复制到一个地方,让我们的Exchange服务器去接收并发送。我相信还有很多其他的用法。

2

我用的是这个:


import os, tempfile, gc


class TemporaryFile:
    def __init__(self, name, io, delete):
        self.name = name
        self.__io = io
        self.__delete = delete

    def __getattr__(self, k):
        return getattr(self.__io, k)

    def __del__(self):
        if self.__delete:
            try:
                os.unlink(self.name)
            except FileNotFoundError:
                pass


def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix='', prefix='tmp', dir=None, delete=True):
    if not dir:
        dir = tempfile.gettempdir()
    name = os.path.join(dir, prefix + os.urandom(32).hex() + suffix)
    if mode is None:
        return TemporaryFile(name, None, delete)
    fh = open(name, "w+b", bufsize)
    if mode != "w+b":
        fh.close()
        fh = open(name, mode)
    return TemporaryFile(name, fh, delete)


def test_ntf_txt():
    x = NamedTemporaryFile("w")
    x.write("hello")
    x.close()
    assert os.path.exists(x.name)
    with open(x.name) as f:
        assert f.read() == "hello"


def test_ntf_name():
    x = NamedTemporaryFile(suffix="s", prefix="p")
    assert os.path.basename(x.name)[0] == 'p'
    assert os.path.basename(x.name)[-1] == 's'
    x.write(b"hello")
    x.seek(0)
    assert x.read() == b"hello"


def test_ntf_del():
    x = NamedTemporaryFile(suffix="s", prefix="p")
    assert os.path.exists(x.name)
    name = x.name
    del x
    gc.collect()
    assert not os.path.exists(name)


def test_ntf_mode_none():
    x = NamedTemporaryFile(suffix="s", prefix="p", mode=None)
    assert not os.path.exists(x.name)
    name = x.name
    f = open(name, "w")
    f.close()
    assert os.path.exists(name)
    del x
    gc.collect()
    assert not os.path.exists(name)

这个在所有平台上都能用,你可以关闭它,再打开,等等。

你需要的功能是 mode=None,你可以请求一个临时文件,指定 mode=None,这样就会给你一个带有你想要的目录/后缀/前缀的UUID风格的临时名称。链接里有测试示例,展示了怎么使用。

这基本上和 NamedTemporaryFile 是一样的,不同的是,当返回的对象被垃圾回收时,文件会自动删除……而不是在关闭时删除。

10

这段话的意思是,如果你在文件还没有关闭的时候第二次访问它是可以的。除此之外,你仍然可以使用这个文件的名字,只要在创建 NamedTemporaryFile 时记得加上 delete=False,这样文件在关闭后就不会被删除了。

撰写回答