0

我的对象是一个字典,里面有大约 100 万个对象({} 和 {},有时是 {{}、{{}}、{}...}

在使用 FOR 循环运行项目时,我收到以下行的错误:

lines = fp.readlines()
MemoryError: Fatal Python error: PyEval_RestoreThread: NULL tstate

我对这个对象大约有 5 到 6 个动作要做。尝试在一个迭代循环中完成所有操作 - 会触发此错误。在单独的循环上运行(每个循环执行一个操作) - 前两个循环运行良好,但是,总是在我第三次运行循环时(大约在 80,000 次迭代之后)Python 崩溃(如上所述的内存错误)。

我改变了动作顺序 - 意味着改变了循环顺序,它总是在第三个“for”循环中失败......

我尝试使用更强大、更快的机器,但仍然出现这些错误。

请指教。

附言

4

3 回答 3

3

我想这对你的 RAM 来说太多了。如果可能,您应该真正在一个 for 循环中执行操作,并优化您的迭代以提高内存效率。

fp.readlines()

呃,它一次读入文件的所有行,因此它的所有内容都在内存中。我不知道细节,将文件内容转换为字典的方式。但是如果它依赖于文件中的行,您可以简单地迭代文件,每个迭代步骤都会产生一个新行。

for line in fp:
    # ...

但是,如果您再次将文件中的所有信息存储在字典中,您将再次面临同样的问题。

通过检查(如果可能)重复来优化存储在内存中的数据是 CPU 密集型的,但可能需要降低内存使用率。


在这两个片段执行相同的操作之后,一致性存储和生成器之间的区别应该很明显,但前者比后者更占用内存。请注意,这iterate_to是该函数的完全副本,range/xrange仅用于演示目的。

def iterate_to(num):
    list_ = []
    for i in xrange(num):
        list_.append(i)
    return list_

def operate_on(num):
    list_ = []
    for i in iterate_to(num):
        x = (i ** i + 5) / (i * 2)
        list_.append(x)
    return list_

print sum(operate_on(1000000))

虽然该sum函数对由 返回的列表中的每个元素求和,但每个1000000 个条目(!!) 的operate_on两个列表在内存中是一致的。您可能已经认为它可以提高内存效率。

def iterate_to(num):
    for i in xrange(num):
        yield i

def operate_on(num):
    for i in iterate_to(num):
        x = (i ** i + 5) / (i * 2)
        yield x

print sum(operate_on(1000000))

在此示例中,表达式yield用于使 theiterate_tooperate_on函数都成为生成器函数。在迭代时,每个迭代步骤,直接计算迭代的下一个元素,而不是依赖于先前构造的项目集合。
更多关于发电机在这里

于 2012-10-24T06:59:36.507 回答
2

这很可能是内存问题 - python 2.* 不能使用超过 2Gb 的 RAM。这可能是由于垃圾收集延迟而发生的。安装 gc 库并尝试在密集处理块之后手动调用垃圾收集,例如在每个 FOR 循环之后。用文件内容填充字典后,从文件对象中清除内存。无论如何,从使用 top 命令或任务管理器查看内存消耗开始。

于 2012-10-24T07:28:44.287 回答
0

gc.colletc() 没有解决我的问题。触发更少内存使用的更改是在一个巨大的 {Dictionary} 中遍历我的 1M 对象并将其中一些“移动”到特殊的 [Lists] 对象中。内存。使用率仍然很高(大约 1.7 GB),但目前脚本正在运行并且不再崩溃。谢谢大家的回答,我从这些回复中学到了,这很有帮助。

于 2012-10-25T12:39:11.363 回答