如何优化一个打开并多次读取同一文件的Python脚本?

2024-05-16 00:29:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个代码可以完美地工作,但是它占用了太多内存。在

本质上,这段代码需要一个输入文件(我们称之为索引,即用两列制表符分隔)在第二个输入文件中搜索第1列中的对应项(将其称为数据,即4列制表符分隔),然后将其替换为索引文件中的信息。在

索引的一个例子是:

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

数据示例如下:

^{2}$

因此,当用索引中的相应信息替换数据列1中的值时,结果如下:

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

我将代码分成步骤,因为这样做的目的是计算数据文件中列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)有何建议?在


Tags: 文件代码infordatetimelineslotprint
1条回答
网友
1楼 · 发布于 2024-05-16 00:29:58

如果我能正确理解代码,就不需要引理集了。您可以删除步骤1并替换步骤3中的签入

    if lemmaTAR in lemmas:

直接与

^{pr2}$

关于内存问题-你有没有试着减少你保存在内存中的数据的开销?当前您正在使用嵌套词典。也许一个扁平的数据结构会占用更少的内存,例如一维featfreq需要一个由“%slot-%filler”构造的键。在

相关问题 更多 >