如何在Python中仅删除文件内容

39

我有一个临时文件包含一些内容和一个Python脚本,将一些输出写入这个文件。我想要重复N次这个过程,所以我需要重复使用那个文件(实际上是一个文件数组)。我要删除整个内容,这样下一个循环中临时文件就会变成空的。为了删除内容,我使用以下代码:

def deleteContent(pfile):

    pfile.seek(0)
    pfile.truncate()
    pfile.seek(0) # I believe this seek is redundant

    return pfile

tempFile=deleteContent(tempFile)

我的问题是:是否有其他(更好、更短或更安全)的方法来删除整个内容,而不实际从磁盘中删除临时文件?

类似于 tempFile.truncateAll() 这样的东西?


1
第二个查找确实是多余的。为什么不只是创建一个新的临时文件呢? - Martijn Pieters
因为对于一个常见的脚本运行,我将需要大约400个临时文件而不是10个左右。所以我认为最好回收利用它们。我错了吗? - bartimar
你遇到过任何实际的问题吗?我会创建新的临时文件,让 Python 和操作系统清理掉我关闭的文件。 - Martijn Pieters
实际上,删除和关闭它们会更多地产生混淆的代码行。我对我的解决方案没有问题,我只需要知道更多的方法来做到这一点并测试性能(同时让代码简单)。 - bartimar
2
如果您正在使用tempfile模块,则无需删除任何内容。将临时文件用作上下文管理器(with...),它也将自动关闭。 - Martijn Pieters
5个回答

82
如何在Python中仅删除文件内容
有几种方法可以将文件的逻辑大小设置为0,具体取决于您访问该文件的方式:
清空已打开的文件:
def deleteContent(pfile):
    pfile.seek(0)
    pfile.truncate()

清空已知文件描述符的打开文件:
def deleteContent(fd):
    os.ftruncate(fd, 0)
    os.lseek(fd, 0, os.SEEK_SET)

清空一个已知名称的关闭文件

def deleteContent(fName):
    with open(fName, "w"):
        pass

我有一个包含一些内容的临时文件[...] 我需要重复使用

话虽如此,在一般情况下,重新使用临时文件可能既不高效也不可取。除非您有非常特殊的需求,否则应考虑使用tempfile.TemporaryFile上下文管理器来几乎透明地创建/使用/删除您的临时文件:

import tempfile

with tempfile.TemporaryFile() as temp:
     # do whatever you want with `temp`

# <- `tempfile` guarantees the file being both closed *and* deleted
#     on the exit of the context manager

2
从http://docs.python.org/2/library/stdtypes.html#file.truncate中可以看到,如果指定的大小超过了文件当前的大小,结果将取决于平台:可能的情况包括文件可能保持不变,增加到指定的大小,就像填充了零一样,或者增加到指定的大小,但内容未定义。这就是为什么我没有这样做的原因。 - bartimar
1
@SylvainLeroux 对我来说不是这样的。f = open('foo', 'wb'); f.write('foo'); f.truncate(0); f.write('foo'); print f.tell() 输出 6 - Aya
1
@SylvainLeroux 对我来说内容是 "\x00\x00\x00\x00\x00Bonjour"。在 foo 上执行 xxd 命令以进行检查。因此,实际上,您正在创建一个 稀疏文件 - Aya
2
@SylvainLeroux 无论如何我都会得到前导的NULL值。Linux 忽略 b 标志。来自 fopen(3) 的描述为:“模式字符串还可以包括字母“b”,作为最后一个字符或任何上述两个字符字符串中字符之间的一个字符。这是严格为了与 C89 兼容而设置的,对所有符合 POSIX 标准的系统都没有影响,包括 Linux。” - Aya
@Aya 好的,我可能有点疯了,或者是该去睡觉了?不管怎样,你是对的。我不知道之前做了什么,但是通过仔细重新测试,我在两种情况下都获得了一个稀疏文件。很抱歉浪费了你的时间 ;) 我已经从我的答案中删除了“截断而不寻求”的部分。 - Sylvain Leroux
显示剩余10条评论

7

我认为最简单的方法是以写入模式打开文件,然后关闭它。例如,如果你的文件myfile.dat包含以下内容:

"This is the original content"

那么你可以简单地写成:
f = open('myfile.dat', 'w')
f.close()

这将擦除所有内容。然后,您可以将新内容写入文件:
f = open('myfile.dat', 'w')
f.write('This is the new content!')
f.close()

2

有什么比这更简单的呢:

import tempfile

for i in range(400):
    with tempfile.TemporaryFile() as tf:
        for j in range(1000):
            tf.write('Line {} of file {}'.format(j,i))

这会创建400个临时文件,并向每个临时文件写入1000行。在我的普通电脑上执行时间不到半秒钟。在这种情况下,总共的每个临时文件都是在上下文管理器打开和关闭时创建和删除的。它快速、安全且跨平台。

使用tempfile比试图重新发明它要好得多。


1
我认为在没有 for 循环的情况下使用 seek(0)truncate() 实际上更容易、更好、(也许更快),对 OS/Python 更友好 :) 我担心有人会在重用/回收方面出现问题,但是我的问题仍然是一样的,所以这实际上不是答案。 - bartimar
2
你测试过这个假设吗?你计时看了吗? - dawg

2
你可以这样做:
def deleteContent(pfile):
    fn=pfile.name 
    pfile.close()
    return open(fn,'w')

0
with open(Test_File, 'w') as f:
    f.truncate(0)

我发现这种方式很容易。你可以尝试一下。


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