大数组的RAM错误

时间:2010-03-12 12:05:23

标签: python

我需要随机获取一行的数字,并将每行放在其他数组中,然后获取一行的数字。

我有一个超过400M的大文件。在该文件中,有13496 * 13496个数字,表示13496行和13496个列。我想把它们读成数组。 这是我的代码:

_L1 = [[0 for col in range(13496)] for row in range(13496)]
_L1file = open('distanceCMD.function.txt')
while (i<13496):
    print "i="+str(i)
    _strlf = _L1file.readline()
    _strlf = _strlf.split('\t')
    _strlf = _strlf[:-1]
    _L1[i] = _strlf
    i += 1
_L1file.close()

这是我的错误信息:

MemoryError:
File "D:\research\space-function\ART3.py", line 30, in <module>
  _strlf = _strlf.split('\t')

5 个答案:

答案 0 :(得分:7)

你可能想以另一种方式处理你的问题。逐行处理文件。我认为不需要将整个大文件存储到数组中。否则,您可能想告诉我们您实际上想要做什么。

for line in open("400MB_file"):
     # do something with line.

f=open("file")
for linenum,line in enumerate(f):
    if linenum+1 in [2,3,10]:
         print "there are ", len(line.split())," columns" #assuming you want to split on spaces
         print "100th column value is: ", line.split()[99]
    if linenum+1>10:
         break # break if you want to stop after the 10th line
f.close()

答案 1 :(得分:3)

这是一个简单的例子,你的程序要求的内存比计算机可用的内存多。 13496x13496元素的数组需要182,142,016个“单元”,其中一个单元最少为一个字节(如果存储字符),可能还有几个字节(例如,如果存储浮点数)。我甚至没有考虑你的特定运行时'数组元数据,虽然这通常是一个简单数组上的微小开销。

假设每个数组元素只是一个字节,那么您的计算机需要大约180MB的RAM才能将其整个存储在内存中。试图处理它可能是不切实际的。

你需要以不同的方式思考问题;正如已经提到的,逐行方法可能是更好的选择。或者可能以较小的单位处理网格,可能是10x10或100x100,并汇总结果。或者也许问题本身可以用不同的形式表达,这避免了完全处理整个数据集的需要......?

如果您向我们提供有关数据性质和目标的更多详细信息,也许有人会有想法让任务更易于管理。

答案 2 :(得分:3)

简短回答:Python对象开销正在扼杀你。在64位机器上的Python 2.x中,即使在考虑字符串的内容之前,每个列表条目的字符串列表也会消耗48个字节。对于您描述的阵列大小,这超过了8.7 Gb的开销。 在32位机器上它会好一点:每个列表条目只有28个字节。

更长的解释:你应该知道Python对象本身可能非常大:甚至是简单的对象,如整数,浮点数和字符串。在您的代码中,您最终会得到一个字符串列表列表。在我的(64位)机器上,即使是一个空字符串对象占用40个字节,为此,您需要为指向内存中此字符串对象的列表指针添加8个字节。所以每个条目已经有48个字节,大约是8.7 Gb。鉴于Python一次以8个字节的倍数分配内存,并且你的字符串几乎肯定是非空的,你实际上每个条目看56或64个字节(我不知道你的字符串有多长)。

可能的解决方案:

(1)您可以根据需要将条目从字符串转换为整数或浮点数,从而做得更好。

(2)你可以通过使用Python的array类型(与列表不同!)或使用numpy来更好地 :那么你的整数或者浮点数每个只需4或8个字节。

从Python 2.6开始,您可以使用sys.getsizeof函数获取有关对象大小的基本信息。请注意,如果将其应用于列表(或其他容器),则返回的大小不包括所包含的列表对象的大小;仅用于保存这些对象的结构。这是我机器上的一些值。

>>> import sys
>>> sys.getsizeof("")
40
>>> sys.getsizeof(5.0)
24
>>> sys.getsizeof(5)
24
>>> sys.getsizeof([])
72
>>> sys.getsizeof(range(10))  # 72 + 8 bytes for each pointer
152

答案 3 :(得分:0)

MemoryError例外:

  

当某个操作耗尽时,提升   记忆,但情况可能仍然存在   获救(通过删除一些对象)。   关联的值是一个字符串   表明什么样的(内部)   操作耗尽内存。注意   因为底层的记忆   管理架构(C的malloc()   功能),翻译可能不会   总是能够完全恢复   从这种情况;不过呢   引发异常以便堆栈   如果是,可以打印回溯   逃跑计划是原因。

似乎至少在你的情况下,将整个文件读入内存并不是一个可行的选择。

答案 4 :(得分:0)

替换它:

_strlf = _strlf[:-1]

用这个:

_strlf = [float(val) for val in _strlf[:-1]]

你正在制作一大堆字符串。我可以保证字符串"123.00123214213"在将其转换为浮点时占用的内存要少得多。

您可能希望包含一些空值处理。

您也可以使用numpy的数组类型,但您的问题可能太小而无法理解。