我正在尝试解析一个巨大的日志文件(大约5 GB)。
我只想解析前500,000行,我不想将整个文件读入内存。
基本上,我想执行以下代码正在执行的操作,但使用while
循环而不是for
循环和if
条件。我还想确保不要将整个文件读入内存。
import re
from collections import defaultdict
FILE = open('logs.txt', 'r')
count_words=defaultdict(int)
import pickle
i=0
for line in FILE.readlines():
if i < 500000:
m = re.search('key=([^&]*)', line)
count_words[m.group(1)]+=1
i+=1
csv=[]
for k, v in count_words.iteritems():
csv.append(k+","+str(v))
print "\n".join(csv)
答案 0 :(得分:12)
替换
for line in FILE.readlines():
与
for line in FILE:
以避免将其全部读入内存。然后,要仅处理前500000行,请执行
from itertools import islice
for line in islice(FILE, 500000):
m = re.search('key=([^&]*)', line)
count_words[m.group(1)] += 1
这样您实际上只会加载您正在使用的文件的前缀。 (您当前的程序实际上将遍历整个文件,无论是否将其完全加载到内存中。)
不需要while
循环进行if
检查即可解决此问题。
答案 1 :(得分:5)
调用readlines()
会将整个文件调用到内存中,因此您必须逐行读取,直到达到500,000行或点击EOF(以先到者为准)。这是你应该做的事情:
i = 0
while i < 500000:
line = FILE.readline()
if line == "": # Cuts off if end of file reached
break
m = re.search('key=([^&]*)', line)
count_words[m.group(1)]+=1
i += 1
答案 2 :(得分:3)
这是一种简单的方法:
with open('logs.txt', 'r') as f:
for line_number, line in enumerate(f, start=1):
do_stuff(line)
if line_number > 500000:
break