Windows上的NamedTemporaryFile有什么用?
Python的一个模块叫做tempfile
,里面有两个功能:NamedTemporaryFile
和TemporaryFile
。关于NamedTemporaryFile
的说明中提到:
在某些平台上,打开这个命名临时文件的名字是否可以再次使用,取决于具体的平台(在Unix系统上可以这样做;但在Windows NT或更高版本上就不行)。
那这个文件有名字有什么用呢,如果我不能用这个名字?如果我想在Windows上也能像在Unix上一样使用这个名字,我就得复制代码,把所有提到if _os.name == 'nt'
之类的部分都删掉。
这是怎么回事呢?这肯定是有用的,因为它是这样设计的,但到底有什么用呢?
4 个回答
你不想“把所有的东西都撕掉...”。这样写是有原因的。它的意思是,在文件还打开的时候,你不能再第二次打开它。不要这样做。只用一次,然后扔掉它(毕竟,它是个临时文件)。如果你想要一个永久的文件,就自己创建一个。
“这肯定有什么用,因为它是故意这样编写的,但具体有什么用呢?”嗯,我之前用它来写电子邮件(以二进制格式),然后再把它们复制到一个地方,让我们的Exchange服务器去接收并发送。我相信还有很多其他的用法。
我用的是这个:
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 是一样的,不同的是,当返回的对象被垃圾回收时,文件会自动删除……而不是在关闭时删除。
这段话的意思是,如果你在文件还没有关闭的时候第二次访问它是可以的。除此之外,你仍然可以使用这个文件的名字,只要在创建 NamedTemporaryFile
时记得加上 delete=False
,这样文件在关闭后就不会被删除了。