5

作为我的一个程序的一部分,我想捕获MemoryError并记录它们。目前,我正在使用traceback.format_exception格式化所有其他异常;我也想这样做MemoryError

但是,使用format_exception需要使用更多内存,这正是我在内存不足时无法做到的。

做什么?

当我被抛出时,MemoryError除了终止我还能做什么?理想情况下,我会记录它们然后恢复程序,前提是释放处理程序和 thrower* 之间的堆栈部分已经为我释放了足够的内存。

(*以及那些仅通过从该堆栈部分发出的引用保持活动状态的堆对象)

4

3 回答 3

4

它实际上与“堆栈”无关。PythonMemoryError在系统malloc()(或类似的平台函数)返回时引发NULL. 在这种情况下,实际上并没有分配新的内存!因此,您剩余的空闲内存与触发MemoryError. 例如,在 32 位盒子上的交互式 shell 中:

>>> x = [None] * 10**9
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
MemoryError
>>>

那是无害的。是的,在实际程序中,其他内存可能会随着堆栈展开而被释放。

MemoryError但是,如果再次尝试相同(或类似)任务时“继续”不会导致另一个,那么您的程序肯定有一些不寻常的地方。最明智的做法通常是退出程序并重新开始。

@FredMitchell 保留一些“紧急记忆”的想法可能值得追求。例如,

emergency = 'x' * 10**7

消耗大约 10 MB(在 Python 2 中),主要是“一大块”,你的处理程序可以做

emergency = ""

将其释放回系统。然后malloc()将有一个 10MB 的新连续块可供使用。

但是,最后,我敢打赌,退出会容易得多;-)

于 2013-10-19T19:14:18.777 回答
2

我们最终使用的食谱:

def do_a_generic_memory_hungry_thing(specific_context):
    memory_error = MemoryError(str(specific_context)) # pre-allocate it
    try: memory_hungry_stuff()
    except MemoryError: raise memory_error

事实证明,和之间的痕迹memory_hungry_stuff并不except有趣。有趣的部分是specific_context,所以在这种情况下进行预分配是双重的。

注意:我们在尝试打印时遇到了内存错误(真的:格式)memory_error,所以这不是防弹的。也许结合释放一个哑弹它会做的伎俩。

于 2013-11-20T09:33:17.670 回答
1

一般来说,内存不足错误可能是程序中最难处理的问题,因为您没有可以让您做任何事情的主要资源。也许程序可以在一个脚本中运行,该脚本从输出中检测故障并记录它。

可以尝试使用一些内存,其唯一目的是在内存不足错误时“释放”。但我对 python 中的这种方法并不乐观。

于 2013-10-19T18:46:30.783 回答