我正在尝试从一个很大的XML文件(dblp记录,对于熟悉它的人)中提取一些数据。 为此,我使用在github上找到的快速解析器的略微修改版本,其工作方式如下:
def fast_iter(context, func,*args, **kwargs):
collaborations = [Top level elements I need]
#Bunch of local variables
#read chunk line by line
for event, elem in context:
if elem.tag in collaborations and event == "start":
#Print to console that we are entering a top level element I might need
tag = elem.tag
print(elem.tag,event)
#Additional processing only on the tags I need
if elem.tag == tag and event == 'end':
#Reset local variables
#Print to console that the element is done
print(elem.tag,event)
#Regardless of the outcome of the processing
#Free the memory from the last used element
if event=="end":
elem.clear()
while elem.getprevious() is not None:
del elem.getparent()[0]
del context
#clear chunks
#@func: process_element
#@param elem : parsed data of chunk
#@param fout : file name to write
#@desc: It is handler to write content. just write content to file
def process_element(elem, fout):
#Write to file if I hit a top level element
#That I actually needed
print("writing ... " + elem)
print(elem, file=fout)
if __name__ == "__main__":
fout = open('parsed_data.txt', 'w')
context = etree.iterparse('dblp.xml', load_dtd=True,html=True, events=["start", "end"])
fast_iter(context, process_element, fout)
正如我所提到的,这是一个很大的XML文件(如果我没记错的话,它是2.3GB),因此我希望执行需要一段时间。但是,我注意到,脚本开始运行后,执行速度会越来越慢(如我将起始端打印到控制台的速度所指示),即使该功能在释放内存时不会占用内存在每个周期。
我在这里想念什么?这是因为我要打印太多内容以进行管理,这是预期的行为吗?在这种情况下,如何显示脚本正在处理文件而不降低实际执行速度?
作为补充说明,我想指出,从XML文件构建的Tree是非常独特的;如作者所说:
“ 通常,我们的XML是一个浅但很长的XML记录列表。根元素具有数百万个子元素,但通常没有任何元素比第三级更深。”
>这是我的瓶颈吗?如果是这样,我如何加快执行速度?据我所知,根节点的每个子元素在遇到结束标记后都会立即从内存中删除,因此在文件的增量处理期间应该没有任何问题。