使用python ElementTree时内存不足 编辑:如果将来有人来这里,我使用的解决方案是切换到cElementTree。它不仅使用更少的内存运行,而且速度明显更快。
这适用于大小约为600mb的文件,大于600mb,并且我的内存不足,我有一台16gb的机器。我可以做些什么来读取一个文件中的片段,或者一次读取一定百分比的xml,或者有一种内存占用较少的方法吗使用python ElementTree时内存不足 编辑:如果将来有人来这里,我使用的解决方案是切换到cElementTree。它不仅使用更少的内存运行,而且速度明显更快。,python,xml,elementtree,Python,Xml,Elementtree,这适用于大小约为600mb的文件,大于600mb,并且我的内存不足,我有一台16gb的机器。我可以做些什么来读取一个文件中的片段,或者一次读取一定百分比的xml,或者有一种内存占用较少的方法吗 import csv import xml.etree.ElementTree as ET from lxml import etree import time import sys def main(argv): start_time = time.time() #file_name = '
import csv
import xml.etree.ElementTree as ET
from lxml import etree
import time
import sys
def main(argv):
start_time = time.time()
#file_name = 'sample.xml'
file_name = argv
root = ET.ElementTree(file=file_name).getroot()
csv_file_name = '.'.join(file_name.split('.')[:-1]) + ".txt"
print '\n'
print 'Output file:'
print csv_file_name
with open(csv_file_name, 'w') as file_:
writer = csv.writer(file_, delimiter="\t")
header = [ <the names of the tags here> ]
writer.writerow(header)
tags = [
<bunch of xml tags here>
]
#write the values
# for index in range(8,1000):
for index in range(3,len(root)):
#print index
row=[]
for tagindex,val in enumerate(tags):
searchQuery = "tags"+tags[tagindex]
# print searchQuery
# print root[index]
# print root[index].find(searchQuery).text
if (root[index].find(searchQuery) is None) or (root[index].find(searchQuery).text == None):
row.extend([""])
#print tags[tagindex]+" blank"
else:
row.extend([root[index].find(searchQuery).text])
#print tags[tagindex]+" "+root[index].find(searchQuery).text
writer.writerow(row)
#for i,child in enumerate(root):
#print root[i]
print '\nNumber of elements is: %s' % len(root)
print '\nTotal run time: %s seconds' % (time.time() - start_time)
if __name__ == "__main__":
main(sys.argv[1])
使用ElementTree.iterparse解析XML数据。请参阅文档以获取帮助。使用ElementTree.iterparse解析XML数据。有关帮助,请参阅文档。一些提示:
使用lxml,它的性能非常好
使用iterparse,它可以逐个处理您的文档
然而,iterparse可能会让您大吃一惊,最终可能会导致高内存消耗。要克服这个问题,必须清除对已处理项目的引用,如我最喜欢的关于
使用优化的iterparse的示例脚本fasterparse.py
安装docopt和lxml
编写脚本:
"""For all elements with given tag prints value of selected attribute
Usage:
fastiterparse.py <xmlfile> <tag> <attname>
fastiterparse.py -h
"""
from lxml import etree
from functools import partial
def fast_iter(context, func):
for event, elem in context:
func(elem)
elem.clear()
while elem.getprevious() is not None:
del elem.getparent()[0]
del context
def printattname(elem, attname):
print elem.attrib[attname]
def main(fname, tag, attname):
fun = partial(printattname, attname=attname)
with open(fname) as f:
context = etree.iterparse(f, events=("end",), tag=tag)
fast_iter(context, fun)
if __name__ == "__main__":
from docopt import docopt
args = docopt(__doc__)
main(args["<xmlfile>"], args["<tag>"], args["<attname>"])
结论采用快速iter方法
主要功能是fast_iter函数,或者至少记住清除未使用的元素,删除它们,最后删除上下文
测量可以显示,在某些情况下,脚本运行稍微慢一点,然后没有clear和del,但差异并不显著。内存的优势在于它的局限性,因为当它开始交换时,优化的版本会变得更快,而且如果内存不足,就没有很多其他选项了。几点提示:
使用lxml,它的性能非常好
使用iterparse,它可以逐个处理您的文档
然而,iterparse可能会让您大吃一惊,最终可能会导致高内存消耗。要克服这个问题,必须清除对已处理项目的引用,如我最喜欢的关于
使用优化的iterparse的示例脚本fasterparse.py
安装docopt和lxml
编写脚本:
"""For all elements with given tag prints value of selected attribute
Usage:
fastiterparse.py <xmlfile> <tag> <attname>
fastiterparse.py -h
"""
from lxml import etree
from functools import partial
def fast_iter(context, func):
for event, elem in context:
func(elem)
elem.clear()
while elem.getprevious() is not None:
del elem.getparent()[0]
del context
def printattname(elem, attname):
print elem.attrib[attname]
def main(fname, tag, attname):
fun = partial(printattname, attname=attname)
with open(fname) as f:
context = etree.iterparse(f, events=("end",), tag=tag)
fast_iter(context, fun)
if __name__ == "__main__":
from docopt import docopt
args = docopt(__doc__)
main(args["<xmlfile>"], args["<tag>"], args["<attname>"])
结论采用快速iter方法
主要功能是fast_iter函数,或者至少记住清除未使用的元素,删除它们,最后删除上下文
测量可以显示,在某些情况下,脚本运行稍微慢一点,然后没有clear和del,但差异并不显著。内存的优势在于它的局限性,因为当它开始交换时,优化的版本会变得更快,而且如果内存不足,就没有很多其他选择。使用cElementTree而不是ElementTree
将ET import语句替换为:import xml.etree.cElementTree as ET使用cElementTree而不是ElementTree
将ET import语句替换为:import xml.etree.cElementTree as ET您是否尝试过cElementTree C实现?只需将您的ET import语句替换为:import xml.etree.cElementTree作为ETS。这样一个简单的修复程序,似乎使用了非常少的内存。请作为答案回答,这样我就可以接受了。这并不能回答这个问题,即知道如何以块的形式读取XML数据,而不是在内存中加载完整的文件。也就是说,很高兴知道C实现在内存消耗方面也更高效。虽然它没有回答问题,但它很清楚地解决了我遇到的问题。很高兴知道您的问题已经解决。您尝试过cElementTree C实现吗?只需将您的ET import语句替换为:import xml.etree.cElementTree作为ETS。这样一个简单的修复程序,似乎使用了非常少的内存。请作为答案回答,这样我就可以接受了。这并不能回答这个问题,即知道如何以块的形式读取XML数据,而不是在内存中加载完整的文件。也就是说,很高兴知道C实现在内存消耗方面也更高效。虽然它没有回答问题,但它很清楚地解决了我遇到的问题。很高兴知道你的问题已经解决了。
$ python fastiterparse.py
Usage:
fastiterparse.py <xmlfile> <tag> <attname>
fastiterparse.py -h
$ python fastiterparse.py large.xml ElaboratedRecord id
rec26872
rec25887
rec26873
rec26874