作为我的一个程序的一部分,我想抓住任何MemoryError
并记录它们。目前,我正在使用traceback.format_exception
格式化所有其他异常;我也想为MemoryError
做这件事。
然而,使用format_exception
需要使用更多内存,这正是我内存不足时无法做到的。
做什么?
除了终止MemoryError
之外,我还能做什么?理想情况下,我会记录它们然后恢复程序,假设释放处理程序和thrower *之间的堆栈部分已经释放了足够的内存供我这样做。
(*并且那些堆对象只能通过从堆栈部分发出的引用保持活动状态)
答案 0 :(得分:4)
它与“堆栈”没什么关系。当系统MemoryError
(或类似的平台函数)返回malloc()
时,Python会引发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的新连续块来处理。
但是,最后,我敢打赌它会更容易退出; - )
答案 1 :(得分: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
的内存错误,因此这不是防弹。也许结合发布一个dud字符串,它就可以解决问题。
答案 2 :(得分:1)
一般情况下,内存不足错误可能是您程序中最棘手的问题,因为您不在主要资源之内,可以让您做任何事情。也许该程序可以在一个脚本中运行,该脚本从输出中检测故障并记录它。
你可以尝试使用一些内存,其唯一目的是在内存不足错误时“释放”。但我对python中的这种方法并不乐观。