2012-03-08 73 views
1

我想解析一个巨大的日志文件(大约5 GB)。在Python中解析巨大的日志文件

我只想解析前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) 

回答

5

调用readlines()将调用整个文件到内存中,所以你必须逐行读取直到第56行50万打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 
12

更换

for line in FILE.readlines(): 

for line in FILE: 

,以避免将其读入的全部记忆。然后,仅处理第一个50万线,做

from itertools import islice 

for line in islice(FILE, 500000): 
    m = re.search('key=([^&]*)', line) 
    count_words[m.group(1)] += 1 

,所以你只实际加载你正在使用的文件的前缀。 (您目前的方案实际上将整个文件,无论它是否加载到内存完全。回路)

没有必要的while循环与if检查,以解决这个问题。

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