我需要迭代文件中的单词。文件可能非常大(超过1TB),线条可能很长(可能只有一行)。单词是英语,大小合理。所以我不想加载整个文件甚至整行。
我有一些可行的代码,但如果行长(在我的机器上超过~3GB)可能会爆炸。
def words(file):
for line in file:
words=re.split("\W+", line)
for w in words:
word=w.lower()
if word != '': yield word
你能告诉我怎样才能简单地重写这个迭代器函数,使它在内存中不会超过需要的数量吗?
答案 0 :(得分:5)
不要逐行阅读,而是以缓冲的块读取:
import re
def words(file, buffersize=2048):
buffer = ''
for chunk in iter(lambda: file.read(buffersize), ''):
words = re.split("\W+", buffer + chunk)
buffer = words.pop() # partial word at end of chunk or empty
for word in (w.lower() for w in words if w):
yield word
if buffer:
yield buffer.lower()
我正在使用iter()
function的callable-and-sentinel版本来处理从文件读取,直到file.read()
返回一个空字符串;我更喜欢这种形式而不是while
循环。
如果您使用的是Python 3.3或更高版本,则可以在此处使用generator delegation:
def words(file, buffersize=2048):
buffer = ''
for chunk in iter(lambda: file.read(buffersize), ''):
words = re.split("\W+", buffer + chunk)
buffer = words.pop() # partial word at end of chunk or empty
yield from (w.lower() for w in words if w)
if buffer:
yield buffer.lower()
演示使用小块大小来演示这一切都按预期工作:
>>> demo = StringIO('''\
... Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque in nulla nec mi laoreet tempus non id nisl. Aliquam dictum justo ut volutpat cursus. Proin dictum nunc eu dictum pulvinar. Vestibulum elementum urna sapien, non commodo felis faucibus id. Curabitur
... ''')
>>> for word in words(demo, 32):
... print word
...
lorem
ipsum
dolor
sit
amet
consectetur
adipiscing
elit
pellentesque
in
nulla
nec
mi
laoreet
tempus
non
id
nisl
aliquam
dictum
justo
ut
volutpat
cursus
proin
dictum
nunc
eu
dictum
pulvinar
vestibulum
elementum
urna
sapien
non
commodo
felis
faucibus
id
curabitur