我有一个大型的XML文件,其条目如
<data num_entries="1000000000">
<item value="3.1324213213"></item>
<item value="6.2432343213"></item>
<!-- ... -->
</data>
(实际上,有多个data
条目,它们在XML树中更深入,但让我们保持简单。)
我想用Python读取这个文件并将所有item
s放入一个numpy数组中。该文件太大,以至于ET.parse()
不是一个选项。为了避免内存窒息,我正在使用iterparse()
和elem.clear()
一样
import xml.etree.cElementTree as ET
items = []
for event, elem in ET.iterparse(filename):
if elem.tag == 'item':
items.append(float(elem.attrib['value']))
elem.clear()
items = numpy.array(items)
这是有效的,但是由于items
是逐位分配的,因此相当慢。我想使用周围的num_entries
块的data
信息来首先分配数组,即像
items = None
k = 0
for event, elem in ET.iterparse(filename):
if elem.tag == 'item':
if items is None:
num_entries = get_num_entries_somehow()
items = numpy.empty(num_entries)
items[k] = float(elem.attrib['value'])
k += 1
elem.clear()
不幸的是,iterparse
只有在所有item
s迭代完毕后才能进入父元素。
如何使用iterparse()
访问父属性?
您可以通过以下方式从xml的根目录获取num_entries
:
tree = ET.ElementTree(file=filename)
root = tree.getroot()
print(root.attrib.get('num_entries'))
^上面的方法将立即解析所有树,这是不好的。
如何启用start
事件?
for event, elem in ET.iterparse(filename, events=('start', 'end')):
if elem.tag == 'data' and event == 'start':
print(elem.attrib['num_entries'])
if elem.tag == 'item' and event == 'start':
items.append(float(elem.attrib['value']))
elem.clear()