glo*_*mph 5 python xml memory iterparse
我正在使用 .xml 处理大型 xml 文件lxml.iterparse。这很有效,但随着我的文件最近变得更大,我发现 iterparse 行为填满了我的记忆。考虑以下代码,该代码写入一个包含 300000 个元素和 300000 个elem元素和 300000 个other_elem元素的文件:
els = ('<elem><subel1>{0}</subel1><subel2>{0}</subel2><subel3>{0}</subel3><subel4>{0}</subel4><subel5>{0}</subel5><subel6>{0}</subel6></elem>'.format(x) for x in range(300000))
other_els = ('<other_elem><subel1>{0}</subel1><subel2>{0}</subel2><subel3>{0}</subel3><subel4>{0}</subel4><subel5>{0}</subel5><subel6>{0}</subel6></other_elem>'.format(x) for x in range(300000))
with open('/tmp/test.xml', 'w') as fp:
fp.write('<root>\n')
fp.write('<elements>\n')
for el in els:
fp.write(el+'\n')
fp.write('</elements>\n')
fp.write('<other_elements>\n')
for el in other_els:
fp.write(el+'\n')
fp.write('</other_elements>\n')
fp.write('</root>\n')
Run Code Online (Sandbox Code Playgroud)
然后我使用以下内容仅解析elem(而不对它们做任何事情),同时不时打印内存使用情况:
from lxml import etree
import psutil
import os
process = psutil.Process(os.getpid())
gen = etree.iterparse('/tmp/test.xml', tag='elem')
elscount = 0
for ac,el in gen:
elscount += 1
el.clear()
if el.getprevious() is not None:
del(el.getparent()[0])
if elscount % 10000 == 0:
print process.get_memory_info().rss/(1024*1024)
print process.get_memory_info().rss/(1024*1024)
Run Code Online (Sandbox Code Playgroud)
输出显示内存使用率低,直到最后突然跳跃。当我尝试读取不包含other_elems的文件时,此行为消失。一种较慢的解决方法是tag忽略 iterparse的参数,而是使用 if 构造进行测试,从而使内存空闲,可能是因为它可以el.clear()对不匹配的元素进行处理。因此,我的问题不是如何解决这个问题,而是为什么 iterparse 在不必输出的元素上浪费内存,或者可能,我在这里做错了什么?