【问题标题】:How to debug Python memory fault?如何调试 Python 内存故障?
【发布时间】:2013-03-08 19:44:54
【问题描述】:

编辑:非常感谢您在寻找错误方面的帮助 - 但由于它可能很难找到/重现,任何一般的调试帮助也将不胜感激!帮我帮自己! =)

编辑 2:缩小范围,注释掉代码。

编辑 3:似乎 lxml 可能不是罪魁祸首,谢谢!完整的脚本是here。我需要仔细阅读它以寻找参考。它们长什么样子?

编辑 4:实际上,脚本在此停止(100%), parse_og 其中的一部分。所以编辑 3 是错误的 - 它一定是 lxml。

编辑 5 主要编辑:正如下面的 David Robinson 和 TankorSmash 所建议的那样,我发现了一种 data 内容,它将在疯狂循环中发送 lxml.etree.HTML( data )。 (我不小心忽略了它,但发现我的罪已被赎回,因为我付出了额外两天调试的代价!;)A working crashing script is here.(Also opened a new question.)

编辑 6:原来这是 lxml 2.7.8 及以下版本的错误(在 至少)。 Updated to lxml 2.9.0,并且错误消失了。还要感谢this follow-up question.

我不知道如何调试我遇到的这个奇怪的问题。 下面的代码可以正常运行大约 5 分钟,这时 RAM 突然被完全填满(在 100% 期间从 200MB 到 1700MB - 然后当内存已满时,它进入蓝色等待状态)。

这是由于下面的代码,特别是前两行。这是肯定的。但这是怎么回事?什么可以解释这种行为?

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

【问题讨论】:

  • 你能链接 HTML data 以便我们也可以测试代码吗?
  • 不难,但是你已经尝试过各种页面,你传入的数据是什么并不重要?
  • @knutole:也许这些特定页面的某些属性导致它崩溃。你能举一个例子吗?
  • @knutole:大概这些页面有一些共同点(这就是选择它们的原因?)无论如何,您不能提供其中任何一个作为示例吗? (到目前为止我也无法重现它)。
  • 在整个 for i in m: 循环被注释掉的情况下还会发生吗?如果是这样,问题可能会超出常规,例如,如果输入的 html 文本被保留(尽管 300 秒内每秒 20 页的 5000 字节页面只有 30 兆字节)。如果由于 6000 个操作,内存使用量变化 1GB,那么每个操作大约 167KB。一个典型的tree 有多大?另外,你可以说del m, tree,而不是tree = ''m = ''

标签: python debugging memory lxml


【解决方案1】:

你可以试试Low-level Python debugging with GDB。可能 Python 解释器或 lxml 库中存在错误,如果没有额外的工具很难找到它。

当 CPU 使用率达到 100% 时,您可以中断在 gdb 下运行的脚本并查看堆栈跟踪。这可能有助于理解脚本内部发生的事情。

【讨论】:

    【解决方案2】:

    这一定是由于一些参考资料使文档保持活力。必须始终小心 xpath 评估的字符串结果。我看到您已将None 分配给treem,但没有分配给y,xi

    您也可以将None 分配给yxi

    【讨论】:

    • 是的,没有运气。谢谢!更新的问题。
    【解决方案3】:

    在尝试追踪内存问题时,工具也很有帮助。我发现guppy 是一个非常有用的 Python 内存分析和探索工具。

    由于缺乏好的教程/文档,这并不是最容易上手的,但是一旦你掌握了它,你会发现它非常有用。我使用的功能:

    • 远程内存分析(通过套接字)
    • 用于图表使用的基本 GUI,可选择显示实时数据
    • 强大且一致的接口,用于在 Python shell 中探索数据使用情况

    【讨论】:

    • 谢谢。你能用这个工具找到“丢失”的引用吗?
    • @knutole:通过一些努力,是的。您可以拍摄内存状态的快照(即问题的可疑触发器之前和之后)并进行比较。所以你只能看到变化。从那里您可以获得全局范围和感兴趣的对象之间的最短路径。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-28
    • 2017-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多