Python中的MemoryError

时间:2015-09-17 09:01:55

标签: python

我有文本文件,其大小为300 MB。我想阅读它,然后打印50个最常用的单词。当我运行程序时,它给了我MemoryError。我的代码如下: -

import sys, string 
import codecs 
import re
from collections import Counter
import collections
import itertools
import csv
import re
import unicodedata


words_1800 = []

with open('E:\\Book\\1800.txt', "r", encoding='ISO-8859-1') as File_1800:
   for line in File_1800:
       sepFile_1800 = line.lower()
       words_1800.extend(re.findall('\w+', sepFile_1800))


for wrd_1800 in [words_1800]:
       long_1800=[w for w in words_1800 if len(w)>3]
       common_words_1800 = dict(Counter(long_1800).most_common(50))

print(common_words_1800)

它给我以下错误: -

Traceback (most recent call last):
File "C:\Python34\CommonWords.py", line 17, in <module>
words_1800.extend(re.findall('\w+', sepFile_1800))
MemoryError

4 个答案:

答案 0 :(得分:4)

您可以使用generator container代替列表来存储re.findall的结果,该结果在内存使用方面进行了优化,您也可以使用re.finditer代替{{1}返回一个迭代器。

findall

然后with open('E:\\Book\\1800.txt', "r", encoding='ISO-8859-1') as File_1800: words_1800=(re.findall('\w+', line.lower()) for line in File_1800) 将是一个包含已创建单词列表的迭代器或使用

words_1800

获取迭代器包含迭代器。

答案 1 :(得分:3)

您可以使用Counter预先使用中间列表来保存内存(尤其是words_1800,这与您正在阅读的文件一样大):

common_words_1800 = Counter()

with open('E:\\Book\\1800.txt', "r", encoding='ISO-8859-1') as File_1800:
    for line in File_1800:
        for match in re.finditer(r'\w+', line.lower()):
            word = match.group()
            if len(word) > 3:
                common_words_1800[word] += 1

print(common_words_1800.most_common(50))

答案 2 :(得分:1)

如果您的文件包含ascii,则不需要正则表达式,您可以拆分单词并使用生成器表达式创建计数器的标点符号:

from string import punctuation
from collections import Counter

with open('E:\\Book\\1800.txt') as f:
   cn = Counter(wrd for line in f for wrd in (w.rstrip(punctuation)
            for w in line.lower().split()) if len(wrd) > 3)
   print(cn.most_common(50))

如果您使用正则表达式,则应首先编译它,然后将其与生成器一起使用:

from collections import Counter
import re
with open('E:\\Book\\1800.txt') as f:
    r = re.compile("\w+")
    cn = Counter(wrd for line in f  
                 for wrd in r.findall(line) if len(wrd) > 3)
    print(cn.most_common(50))

答案 3 :(得分:0)

您的代码运行良好,但它看起来有点内存效率低下。如果您的文件有300 MB,那么可以处理很多单词。尝试使用@Kasramvd提供的建议。使用迭代器而不是完整列表似乎是个好主意。

此外,这是一篇关于在python中检查内存使用情况和分析应用程序的精美博文 - Python - memory usage