如何调试Python内存故障?
编辑:非常感谢大家帮我找出bug,但由于可能很难找到或重现,任何一般的调试建议也会非常感激!帮我帮自己!=)
编辑2:正在缩小范围,注释掉一些代码。
编辑3:看起来lxml可能不是问题所在,谢谢!完整的脚本在这里。我需要仔细检查一下,找找里面的引用。它们看起来是什么样的呢?
编辑4:实际上,脚本在这个部分停止(达到100%),就是parse_og
部分。所以编辑3是错误的——问题肯定出在lxml上。
编辑5 重大编辑:根据David Robinson和TankorSmash的建议,我发现了一种data
内容会让lxml.etree.HTML(data)
陷入疯狂循环。(我之前不小心忽略了这个,但我为自己的错误付出了代价,调试多花了两天时间! ;) 一个导致崩溃的有效脚本在这里。 (我也开了一个新问题。)
编辑6:结果发现这是lxml 2.7.8及以下版本的一个bug(至少是这样)。更新到lxml 2.9.0后,bug消失了。也感谢在这个后续问题中的朋友们。
我不知道怎么调试我遇到的这个奇怪问题。下面的代码运行大约五分钟后,内存突然被完全占满(从200MB飙升到1700MB,在达到100%期间——然后当内存满了,就进入蓝色等待状态)。
这肯定是因为下面的代码,特别是前两行。但到底发生了什么?有什么可能解释这种行为吗?
def parse_og(self, data):
""" lxml parsing to the bone! """
try:
tree = etree.HTML( data ) # << break occurs on this line >>
m = tree.xpath("//meta[@property]")
#for i in m:
# y = i.attrib['property']
# x = i.attrib['content']
# # self.rj[y] = x # commented out in this example because code fails anyway
tree = ''
m = ''
x = ''
y = ''
i = ''
del tree
del m
del x
del y
del i
except Exception:
print 'lxml error: ', sys.exc_info()[1:3]
print len(data)
pass
3 个回答
这可能是因为有一些引用让文档保持活跃。使用 xpath 评估得到的字符串结果时,必须小心。我看到你把 None
赋值给了 tree
和 m
,但没有给 y
、x
和 i
赋值。
你能把 None
也赋值给 y
、x
和 i
吗?
在解决内存问题时,工具也会很有帮助。我发现guppy是一个非常实用的Python内存分析和探索工具。
虽然它的入门并不简单,因为缺乏好的教程和文档,但一旦你掌握了它,就会觉得它非常有用。我常用的功能有:
- 远程内存分析(通过套接字)
- 基本的图形界面,可以绘制使用情况图表,还可以选择显示实时数据
- 强大且一致的接口,可以在Python命令行中探索数据使用情况
你可以试试使用GDB进行低级Python调试。可能是Python解释器或者lxml库里有个bug,没用额外的工具很难找到。
当你的脚本在gdb下运行时,如果CPU使用率达到100%,你可以中断脚本,然后查看堆栈跟踪。这可能会帮助你理解脚本内部发生了什么。