为什么这个lxml.etree.HTMLPullParser会泄漏内存?

时间:2015-04-29 16:13:26

标签: python lxml.html

我正在尝试在Linux Mint上使用lxml的HTMLPullParser,但我发现内存使用量不断增加,我不知道为什么。这是我的测试代码:

# -*- coding: utf-8 -*-
from __future__ import division, absolute_import, print_function, unicode_literals
import lxml.etree
import resource
from io import DEFAULT_BUFFER_SIZE

for _ in xrange(1000):
with open('StackOverflow.html', 'r') as f:
    parser = lxml.etree.HTMLPullParser()
    while True:
        buf = f.read(DEFAULT_BUFFER_SIZE)
        if not buf: break
        parser.feed(buf)
    parser.close()

    # Print memory usage
    print((resource.getrusage(resource.RUSAGE_SELF)[2] * resource.getpagesize())/1000000.0)

StackOverflow.html是stackoverflow的主页,我将其保存在与python脚本相同的文件夹中。我已经尝试添加显式删除和清除,但到目前为止没有任何工作。我做错了什么?

1 个答案:

答案 0 :(得分:1)

解析器构造的元素正在泄漏,我无法在代码中看到导致它的API合同违规。由于对象在使用gc.collect()运行的手动垃圾回收中幸存,因此最好的办法是尝试使用不同的解析策略作为解决方法。

要查看根本原因,我使用了内存探索模块objgraph并安装了xdot来查看它创建的图表。

在运行代码之前,我跑了:

In [3]: import objgraph

In [4]: objgraph.show_growth()

运行代码后,我跑了:

In [6]: objgraph.show_growth()
tuple                  1616      +147
_Element                146      +146
list                   1100       +24
wrapper_descriptor     1423       +15
weakref                1155        +6
getset_descriptor       677        +4
dict                   2777        +4
member_descriptor       315        +3
method_descriptor       891        +2
_TempStore                2        +1

In [7]: import random

In [8]: objgraph.show_chain(
   ...: objgraph.find_backref_chain(
   ...: random.choice(objgraph.by_type('_Element')), objgraph.is_proper_module))
Graph written to /tmp/objgraph-bfuwa9.dot (8 nodes)
Spawning graph viewer (xdot)

注意:根据所查看的网页,这些数字可能与您看到的数字不同。