Python LXML iterparse 函数:解析巨大的内存时未释放内存 XML
Python LXML iterparse function: memory not getting freed while parsing a huge XML
我正在 Python 中的 LXML 库的帮助下解析大 XMLs (~500MB)。我已经将 BeautifulSoup 与 lxml-xml 解析器一起用于小文件。但是当我遇到巨大的 XMLs 时,它是低效的,因为它读取整个文件一次,然后解析它。
我需要解析 XML 以获得从根到叶的路径(除了最外层的标记)。
例如
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE A>
<A>
<B>
<C>
abc
</C>
<D>
abd
</D>
</B>
</A>
以上 XML 应该给出键和值作为输出(根到叶路径)。
A.B.C = abc
A.B.D = abd
这是我为解析它而编写的代码:
(ignore1 和 ignore2 是需要忽略的标签,tu.clean_text() 是去除不需要字符的函数)
def fast_parser(filename, keys, values, ignore1, ignore2):
context = etree.iterparse(filename, events=('start', 'end',))
path = list()
i = 0
lastevent = ""
for event, elem in context:
i += 1
tag = elem.tag if "}" not in elem.tag else elem.tag.split('}', 1)[1]
if tag == ignore1 or tag == ignore2:
pass
elif event == "start":
path.append(tag)
elif event == "end":
if lastevent == "start":
keys.append(".".join(path))
values.append(tu.clean_text(elem.text))
# free memory
elem.clear()
while elem.getprevious() is not None:
del elem.getparent()[0]
if len(path) > 0:
path.pop()
lastevent = event
del context
return keys, values
我已经参考了以下解析大文件的文章ibm.com/developerworks/xml/library/x-hiperfparse/#listing4
这是top命令的截图。 ~500 MB XML 文件的内存使用量超过 2 GB。我怀疑内存没有被释放。
我已经回答了几个 Whosebug 问题。但这没有帮助。请指教
我从 中获取了代码,切掉了注释和打印语句,并添加了合适的 func
来得到这个。我不想猜测处理一个 500 Mb 的文件需要多少时间!
即使在写作中func
我也没有做任何原创,采用了原作者对 xpath 表达式的使用,'ancestor-or-self::*',以提供您想要的绝对路径。
但是,由于此代码更符合原始脚本,因此它可能不会泄漏内存。
import lxml.etree as ET
input_xml = 'temp.xml'
for line in open(input_xml).readlines():
print (line[:-1])
def mod_fast_iter(context, func, *args, **kwargs):
for event, elem in context:
func(elem, *args, **kwargs)
elem.clear()
for ancestor in elem.xpath('ancestor-or-self::*'):
while ancestor.getprevious() is not None:
del ancestor.getparent()[0]
del context
def func(elem):
content = '' if not elem.text else elem.text.strip()
if content:
ancestors = elem.xpath('ancestor-or-self::*')
print ('%s=%s' % ('.'.join([_.tag for _ in ancestors]), content))
print ('\nResult:\n')
context = ET.iterparse(open(input_xml , 'rb'), events=('end', ))
mod_fast_iter(context, func)
输出:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE A>
<A>
<B>
<C>
abc
</C>
<D>
abd
</D>
</B>
</A
Result:
A.B.C=abc
A.B.D=abd
我正在 Python 中的 LXML 库的帮助下解析大 XMLs (~500MB)。我已经将 BeautifulSoup 与 lxml-xml 解析器一起用于小文件。但是当我遇到巨大的 XMLs 时,它是低效的,因为它读取整个文件一次,然后解析它。
我需要解析 XML 以获得从根到叶的路径(除了最外层的标记)。
例如
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE A>
<A>
<B>
<C>
abc
</C>
<D>
abd
</D>
</B>
</A>
以上 XML 应该给出键和值作为输出(根到叶路径)。
A.B.C = abc
A.B.D = abd
这是我为解析它而编写的代码:
(ignore1 和 ignore2 是需要忽略的标签,tu.clean_text() 是去除不需要字符的函数)
def fast_parser(filename, keys, values, ignore1, ignore2):
context = etree.iterparse(filename, events=('start', 'end',))
path = list()
i = 0
lastevent = ""
for event, elem in context:
i += 1
tag = elem.tag if "}" not in elem.tag else elem.tag.split('}', 1)[1]
if tag == ignore1 or tag == ignore2:
pass
elif event == "start":
path.append(tag)
elif event == "end":
if lastevent == "start":
keys.append(".".join(path))
values.append(tu.clean_text(elem.text))
# free memory
elem.clear()
while elem.getprevious() is not None:
del elem.getparent()[0]
if len(path) > 0:
path.pop()
lastevent = event
del context
return keys, values
我已经参考了以下解析大文件的文章ibm.com/developerworks/xml/library/x-hiperfparse/#listing4
这是top命令的截图。 ~500 MB XML 文件的内存使用量超过 2 GB。我怀疑内存没有被释放。
我已经回答了几个 Whosebug 问题。但这没有帮助。请指教
我从 中获取了代码,切掉了注释和打印语句,并添加了合适的 func
来得到这个。我不想猜测处理一个 500 Mb 的文件需要多少时间!
即使在写作中func
我也没有做任何原创,采用了原作者对 xpath 表达式的使用,'ancestor-or-self::*',以提供您想要的绝对路径。
但是,由于此代码更符合原始脚本,因此它可能不会泄漏内存。
import lxml.etree as ET
input_xml = 'temp.xml'
for line in open(input_xml).readlines():
print (line[:-1])
def mod_fast_iter(context, func, *args, **kwargs):
for event, elem in context:
func(elem, *args, **kwargs)
elem.clear()
for ancestor in elem.xpath('ancestor-or-self::*'):
while ancestor.getprevious() is not None:
del ancestor.getparent()[0]
del context
def func(elem):
content = '' if not elem.text else elem.text.strip()
if content:
ancestors = elem.xpath('ancestor-or-self::*')
print ('%s=%s' % ('.'.join([_.tag for _ in ancestors]), content))
print ('\nResult:\n')
context = ET.iterparse(open(input_xml , 'rb'), events=('end', ))
mod_fast_iter(context, func)
输出:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE A>
<A>
<B>
<C>
abc
</C>
<D>
abd
</D>
</B>
</A
Result:
A.B.C=abc
A.B.D=abd