2012-03-08 80 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