gpt4 book ai didi

python - 如何高效删除大文件的第一行?

转载 作者:太空宇宙 更新时间:2023-11-03 15:55:18 25 4
gpt4 key购买 nike

这个问题已经有人问过herehere ,但没有一个解决方案对我有用。

如何在 Python 3 中有效地删除大文件的 first 行?

我正在编写一个需要日志记录的程序,日志文件有一个可配置的最大大小,可以是无限的。因此,我不想使用 readlines() 或类似的方法,因为它们会占用大量内存。速度不是一个大问题,但如果无需重写整个文件且无需临时文件即可完成,那就太好了。

解决方案需要跨平台。

示例日志文件:

[09:14:56 07/04/17] [INFO] foo
[23:45:01 07/04/17] [WARN] bar
[13:45:28 08/04/17] [INFO] foobar
... many thousands more lines

输出:

[23:45:01 07/04/17] [WARN] bar
[13:45:28 08/04/17] [INFO] foobar
... many thousands more lines

这段代码将循环运行:

while os.path.getsize(LOGFILE) > MAXLOGSIZE:
# remove first line of file

以下解决方案均无效且内存效率高:

解决方案 #1 - 有效但效率低下

with open('file.txt', 'r') as fin:
data = fin.read().splitlines(True)
with open('file.txt', 'w') as fout:
fout.writelines(data[1:])

解决方案 #2 - 不起作用,将文件留空

import shutil

source_file = open('file.txt', 'r')
source_file.readline()
target_file = open('file.txt', 'w')

shutil.copyfileobj(source_file, target_file)

解决方案 #3 - 有效,高效,但使用额外的文件:

with open("file.txt",'r') as f:
with open("new_file.txt",'w') as f1:
f.next() # skip header line
for line in f:
f1.write(line)

最佳答案

因此,这种方法非常 hacky。如果您的线条大小大致相同且标准偏差较小,则效果会很好。这个想法是将文件的某些部分读入一个缓冲区,该缓冲区足够小以提高内存效率但又足够大以至于从两端写入不会搞砸(因为行的大小大致相同,差异很小,我们可以交叉我们的手指并祈祷它会起作用)。我们基本上跟踪我们在文件中的位置并来回跳转。我使用 collections.deque 作为缓冲区,因为它在两端都有良好的 append 性能,而且我们可以利用队列的 FIFO 特性:

from collections import deque
def efficient_dropfirst(f, dropfirst=1, buffersize=3):
f.seek(0)
buffer = deque()
tail_pos = 0
# these next two loops assume the file has many thousands of
# lines so we can safely drop and buffer the first few...
for _ in range(dropfirst):
f.readline()
for _ in range(buffersize):
buffer.append(f.readline())
line = f.readline()
while line:
buffer.append(line)
head_pos = f.tell()
f.seek(tail_pos)
tail_pos += f.write(buffer.popleft())
f.seek(head_pos)
line = f.readline()
f.seek(tail_pos)
# finally, clear out the buffer:
while buffer:
f.write(buffer.popleft())
f.truncate()

现在,让我们用一个表现良好的假文件来试试这个:

>>> s = """1. the quick
... 2. brown fox
... 3. jumped over
... 4. the lazy
... 5. black dog.
... 6. Old McDonald's
... 7. Had a farm
... 8. Eeyi Eeeyi Oh
... 9. And on this farm they had a
... 10. duck
... 11. eeeieeeiOH
... """

最后:

>>> import io
>>> with io.StringIO(s) as f: # we mock a file
... efficient_dropfirst(f)
... final = f.getvalue()
...
>>> print(final)
2. brown fox
3. jumped over
4. the lazy
5. black dog.
6. Old McDonald's
7. Had a farm
8. Eeyi Eeeyi Oh
9. And on this farm they had a
10. duck
11. eeeieeeiOH

如果 dropfirst <buffersize 稍微“松弛”一点,这应该可以解决问题。由于您只想删除第一行,因此只需保留 dropfirst=1,并且您可以设置 buffersize=100 或其他安全起见。它比读取“数千行”的内存效率高得多,如果没有一行比前面的行大,你应该是安全的。但请注意,边缘非常粗糙。

关于python - 如何高效删除大文件的第一行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43715675/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com