2014-03-01 35 views
0

我有一个完美的代码,但它使用了太多的内存。如何优化打开并读取多次相同文件的python脚本?

本质上,这段代码需要一个输入文件(让它称为一个索引,即2列制表符分隔),在第二个输入文件中进行搜索(让它称为数据,即4列制表符分隔)在第一列中将其替换为索引文件中的信息。

索引的例子是:

amphibian anm|art|art|art|art 
anaconda anm 
aardvark anm 

的数据的一个例子是:

amphibian-n is green 10 
anaconda-n is green 2 
anaconda-n eats mice 1 
aardvark-n eats plants 1 

因此,在西1与从索引对应的信息来替换数据的值时,结果如下:

anm-n is green 
art-n is green 
anm-n eats mice 
anm-n eats plants 

我在步骤中划分了代码,因为我dea是计算数据文件中第2列和第3列替换项(数据第4列)的值的平均值。这个代码采取在数据文件中时隙的填料的总数量并总结其在步骤中使用的值3.

期望的结果如下:

anm second hello 1.0 
anm eats plants 1.0 
anm first heador 0.333333333333 
art first heador 0.666666666667 

我打开相同的在步骤1,2和3中多次输入文件(即3次),因为我需要创建一些需要以特定顺序创建的字典。 有没有方法可以优化我打开同一个输入文件的次数?

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

from __future__ import division 
from collections import defaultdict 

import datetime 

print "starting:", 
print datetime.datetime.now() 

mapping = dict() 

with open('input-map', "rb") as oSenseFile: 
    for line in oSenseFile: 
     uLine = unicode(line, "utf8") 
     concept, conceptClass = uLine.split() 
     if len(concept) > 2: 
       mapping[concept + '-n'] = conceptClass 


print "- step 1:", 
print datetime.datetime.now() 

lemmas = set() 

with open('input-data', "rb") as oIndexFile: 
    for line in oIndexFile: 
     uLine = unicode(line, "latin1") 
     lemma = uLine.split()[0] 
     if mapping.has_key(lemma): 
      lemmas.add(lemma) 

print "- step 2:", 
print datetime.datetime.now() 


featFreqs = defaultdict(lambda: defaultdict(float)) 

with open('input-data', "rb") as oIndexFile:    
    for line in oIndexFile: 
     uLine = unicode(line, "latin1") 
     lemmaTAR, slot, filler, freq = uLine.split() 
     featFreqs[slot][filler] += int(freq) 


print "- step 3:", 
print datetime.datetime.now() 

classFreqs = defaultdict(lambda: defaultdict(lambda: defaultdict(float))) 

with open('input-data', "rb") as oIndexFile:    
    for line in oIndexFile: 
     uLine = unicode(line, "latin1") 
     lemmaTAR, slot, filler, freq = uLine.split() 
     if lemmaTAR in lemmas: 
      senses = mapping[lemmaTAR].split(u'|') 
      for sense in senses: 
       classFreqs[sense][slot][filler] += (int(freq)/len(senses))/featFreqs[slot][filler] 
     else: 
      pass 

print "- step 4:", 
print datetime.datetime.now() 

with open('output', 'wb') as oOutFile: 
    for sense in sorted(classFreqs): 
       for slot in classFreqs[sense]: 
         for fill in classFreqs[sense][slot]: 
           outstring = '\t'.join([sense, slot, fill,\ 
                 str(classFreqs[sense][slot][fill])]) 
           oOutFile.write(outstring.encode("utf8") + '\n') 

如何优化这个代码来处理大的文本文件(例如,> 4GB)任何建议?

+0

什么是优化标准? – User

+1

我正在尝试处理一个4 GB的文件。它在第2步中我的16GB服务器上的内存不足。我希望能够使用服务器中的16 GB RAM来处理整个文件。你会建议什么? – owwoow14

+1

这对你来说可能是不可能的,但是对于这类事情来说,实际的数据库不是一个更好的选择吗? – Tharwen

回答

1

如果我正确理解代码,则不需要设置引理句。你可以在步骤与

if mapping.has_key(lemmaTAR): 

关于内存问题,请删除步骤1中,更换检查3

if lemmaTAR in lemmas: 

直接 - 你试过来减少数据的,你保存在内存开销?目前您正在使用嵌套字典。也许平面数据结构会使用较少的内存,例如一个一维featFreqs,它采用由“%slot-%filler”构造的单个键。

+0

谢谢,这真的解决了我的问题。除了删除步骤1并按照你的建议替换步骤3中的检查外,我还删除了所有的unicode变量,并将featFreq中的'float'更改为'int'。随着这些变化和你的建议,我能够处理整个文件(4GB)与16GB的RAM大约。 30分钟。 – owwoow14