高效地读取/写入/解析大文本文件(python)
假设我有一个非常大的文本文件。我原本认为我的文件不会超过大约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
循环逐行读取。不过你还是得考虑多行句子的问题;而且如果某个句子结束符后面没有空格,你就得插入一个换行符(而不是替换其他字符),这样在处理大文件时可能会非常低效。