如何解决Python中的内存错误

fly*_*use 10 python memory

我正在处理几个大的txt文件,每个文件大约有8000000行.这些行的一个简短例子是:

usedfor zipper fasten_coat
usedfor zipper fasten_jacket
usedfor zipper fasten_pant
usedfor your_foot walk
atlocation camera cupboard
atlocation camera drawer
atlocation camera house
relatedto more plenty
Run Code Online (Sandbox Code Playgroud)

将它们存储在字典中的代码是:

dicCSK = collections.defaultdict(list)
for line in finCSK:
    line=line.strip('\n')
    try:
        r, c1, c2 = line.split(" ")
    except ValueError:
        print line
    dicCSK[c1].append(r+" "+c2)
Run Code Online (Sandbox Code Playgroud)

它在第一个txt文件中运行良好,但是当它运行到第二个txt文件时,我收到了一个错误MemoryError.

我使用的是带有python 2.7 32bit,intel i5 cpu,8Gb内存的7位64位窗口.我该如何解决这个问题?

进一步解释:我有四个大文件,每个文件包含许多实体的不同信息.例如,我想查找cat其父节点animal及其子节点persian cat等的所有信息.所以我的程序首先读取字典中的所有txt文件,然后我扫描所有字典以查找cat其父亲及其子代的信息.

Sha*_*ger 20

最简单的解决方案:您可能已经耗尽虚拟地址空间(任何其他形式的错误通常意味着在您最终获得a之前很长一段时间内运行速度非常慢MemoryError).这是因为Windows(和大多数操作系统)上的32位应用程序仅限于2 GB的用户模式地址空间(Windows可以调整为3 GB,但这仍然是一个低上限).你有8 GB的RAM,但你的程序不能使用(至少)3/4.Python有相当数量的每个对象开销(对象头,分配对齐等),可能是单独的字符串使用接近GB的RAM,并且在你处理字典的开销之前,其余的你的程序,Python的其余部分等等.如果内存空间足够碎片,并且字典需要增长,它可能没有足够的连续空间来重新分配,你就会得到一个MemoryError.

安装64位版本的Python(如果可以,我建议出于其他原因升级到Python 3); 它会使用更多的内存,但随后,它会进入到一个很大更多的存储空间(并物理RAM以及).

如果这还不够,可以考虑转换到sqlite3数据库(或其他一些数据库),因此当数据对于主内存来说太大时,它会自然地溢出到磁盘,同时仍然具有相当高效的查找.

  • 使用`sqlite3`是一个很好的建议。 (3认同)
  • 我刚刚安装了一个64位的python。它比我的原始程序运行得更远,但是在我的一半内存(使用了大约 4Gb)之后我仍然遇到了“内存错误”。我感到奇怪,为什么在仍有一半内存可用时会发生错误。 (2认同)

Lev*_*ker 5

假设您的示例文本代表所有文本,那么在我的机器上一行将消耗约75个字节:

In [3]: sys.getsizeof('usedfor zipper fasten_coat')
Out[3]: 75
Run Code Online (Sandbox Code Playgroud)

做一些粗略的数学运算:

75 bytes * 8,000,000 lines / 1024 / 1024 = ~572 MB
Run Code Online (Sandbox Code Playgroud)

因此大约需要572兆来单独存储这些文件之一的字符串。一旦开始添加其他类似结构和大小的文件,您将迅速达到虚拟地址空间限制,如@ShadowRanger的答案所述。

如果升级python对您而言不可行,或者仅助您一臂之力(毕竟您的物理内存有限),则确实有两个选择:在加载和读取之间将结果写入临时文件输入文件,或将结果写入数据库。由于您需要在汇总字符串后进一步对字符串进行后处理,因此写入数据库将是一种更好的方法。