2012-03-08 18 views
1

巨大なログファイル(約5 GB)を解析しようとしています。PythonでGigantic Log Fileを解析する

最初の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

あなたがライン500,000に達するまで行ずつ読み取りまたはいずれか早い方EOFをヒットする必要がありますので、readlines()を呼び出すと、ファイル全体をメモリに呼び出します。ここでは、代わりに何をすべきかです:

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: 

for line in FILE.readlines(): 

を交換してください。あなただけ実際にあなたが作業しているファイルの接頭辞をロードするように続いて、最初の500000個の行を処理するために、

from itertools import islice 

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

を行います。 (あなたの現在のプログラムは実際にファイル全体をループするかどうかは関係ありません)

この問題を解決するにはifのチェックでwhileループを実行する必要はありません。ここで

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