高效地读取/写入/解析大文本文件(python)

1 投票
1 回答
2205 浏览
提问于 2025-04-17 08:44

假设我有一个非常大的文本文件。我原本认为我的文件不会超过大约500MB,但为了考虑扩展性和我自己的好奇心,假设它的大小在几个GB左右。

我的最终目标是把这个文件中的内容分成一个个句子(句子是用'?'、'!'、'.'和';'来分隔的),然后再把每个句子分成一个个单词。接着,我打算用numpy来做一些统计分析。

那么,最有效的方法是什么呢?

另外,我想过把文件重写成每行一个句子的格式,但在尝试把文件加载到内存时遇到了问题。我知道有一种方法是分块读取文件中的数据,处理后再写入另一个文件,但这样似乎在磁盘内存上不太高效。我知道现在大多数人不会担心使用10GB的临时空间,但我觉得应该有办法直接编辑文件中的某些部分。

1 个回答

5

我首先想到的是使用流解析器:简单来说,就是一次读取文件的一部分,然后边读边进行统计分析。这种方法通常用于像HTML和XML这样的标记语言,所以你会发现有很多针对这些语言的解析器,包括Python标准库里也有。其实你也可以自己写一个简单的句子解析器,比如:

import re, collections
sentence_terminator = re.compile(r'(?<=[.!?;])\s*')
class SentenceParser(object):
    def __init__(self, filelike):
        self.f = filelike
        self.buffer = collections.deque([''])
    def next(self):
        while len(self.buffer) < 2:
            data = self.f.read(512)
            if not data:
                raise StopIteration()
            self.buffer += sentence_terminator.split(self.buffer.pop() + data)
        return self.buffer.popleft()
    def __iter__(self):
        return self

这个解析器只会在需要完成一个句子时才从文件中读取数据。它是以512字节为块来读取的,所以无论文件有多大,你在内存中最多只会保留不到一千字节的内容。

在使用流解析器之后,我第二个想到的就是内存映射文件。这样你就可以逐个检查,并把每个句子结束符后面的空格替换成换行符;这样每个句子就会从新的一行开始,你可以打开文件,用readline()或者for循环逐行读取。不过你还是得考虑多行句子的问题;而且如果某个句子结束符后面没有空格,你就得插入一个换行符(而不是替换其他字符),这样在处理大文件时可能会非常低效。

撰写回答