thc*_*and 5 python xml performance parsing lxml
我试图解析一个范围从(20MB-3GB)的巨大XML文件.文件是来自不同仪器的样本.所以,我正在做的是从文件中找到必要的元素信息并将它们插入数据库(Django).
我文件样本的一小部分.命名空间存在于所有文件中.文件的有趣特征是它们具有比文本更多的节点属性
<?xml VERSION="1.0" encoding="ISO-8859-1"?>
<mzML xmlns="http://psi.hupo.org/ms/mzml" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:schemaLocation="http://psi.hupo.org/ms/mzml http://psidev.info/files/ms/mzML/xsd/mzML1.1.0.xsd" accession="plgs_example" version="1.1.0" id="urn:lsid:proteios.org:mzml.plgs_example">
<instrumentConfiguration id="QTOF">
<cvParam cvRef="MS" accession="MS:1000189" name="Q-Tof ultima"/>
<componentList count="4">
<source order="1">
<cvParam cvRef="MS" accession="MS:1000398" name="nanoelectrospray"/>
</source>
<analyzer order="2">
<cvParam cvRef="MS" accession="MS:1000081" name="quadrupole"/>
</analyzer>
<analyzer order="3">
<cvParam cvRef="MS" accession="MS:1000084" name="time-of-flight"/>
</analyzer>
<detector order="4">
<cvParam cvRef="MS" accession="MS:1000114" name="microchannel plate detector"/>
</detector>
</componentList>
</instrumentConfiguration>
Run Code Online (Sandbox Code Playgroud)
小但完整的文件在这里
所以我到目前为止所做的就是将findall用于所有感兴趣的元素.
import xml.etree.ElementTree as ET
tree=ET.parse('plgs_example.mzML')
root=tree.getroot()
NS="{http://psi.hupo.org/ms/mzml}"
s=tree.findall('.//{http://psi.hupo.org/ms/mzml}instrumentConfiguration')
for ins in range(len(s)):
insattrib=s[ins].attrib
# It will print out all the id attribute of instrument
print insattrib["id"]
Run Code Online (Sandbox Code Playgroud)
如何访问instrumentConfiguration(s)元素的所有子/孙?
s=tree.findall('.//{http://psi.hupo.org/ms/mzml}instrumentConfiguration')
Run Code Online (Sandbox Code Playgroud)
我想要的例子
InstrumentConfiguration
-----------------------
Id:QTOF
Parameter1: T-Tof ultima
source:nanoelectrospray
analyzer: quadrupole
analyzer: time-of-flight
detector: microchannel plate decector
Run Code Online (Sandbox Code Playgroud)
当命名空间存在时,是否有有效的方法来解析元素/子元素/子元素?或者我每次都必须使用find/findall来访问具有命名空间的树中的特定元素?这只是我必须解析更复杂的元素层次结构的一个小例子.
有什么建议!
编辑
没有得到正确答案所以必须再次编辑!
这是一个脚本,可以在几秒钟内(在我的机器上)解析一百万个<instrumentConfiguration/>元素(967MB文件),40而不会占用大量内存。
吞吐量为24MB/s。该cElementTree page (2005)报告47MB/s。
#!/usr/bin/env python
from itertools import imap, islice, izip
from operator import itemgetter
from xml.etree import cElementTree as etree
def parsexml(filename):
it = imap(itemgetter(1),
iter(etree.iterparse(filename, events=('start',))))
root = next(it) # get root element
for elem in it:
if elem.tag == '{http://psi.hupo.org/ms/mzml}instrumentConfiguration':
values = [('Id', elem.get('id')),
('Parameter1', next(it).get('name'))] # cvParam
componentList_count = int(next(it).get('count'))
for parent, child in islice(izip(it, it), componentList_count):
key = parent.tag.partition('}')[2]
value = child.get('name')
assert child.tag.endswith('cvParam')
values.append((key, value))
yield values
root.clear() # preserve memory
def print_values(it):
for line in (': '.join(val) for conf in it for val in conf):
print(line)
print_values(parsexml(filename))
Run Code Online (Sandbox Code Playgroud)
$ /usr/bin/time python parse_mxml.py
Id: QTOF
Parameter1: Q-Tof ultima
source: nanoelectrospray
analyzer: quadrupole
analyzer: time-of-flight
detector: microchannel plate detector
38.51user 1.16system 0:40.09elapsed 98%CPU (0avgtext+0avgdata 23360maxresident)k
1984784inputs+0outputs (2major+1634minor)pagefaults 0swaps
Run Code Online (Sandbox Code Playgroud)
注意:该代码易碎,它假定<instrumentConfiguration/>are <cvParam/>和的前两个子代,<componentList/>并且所有值都可用作标记名或属性。
在这种情况下,ElementTree 1.3比cElementTree 1.0.6慢约6倍。
如果您替换为root.clear(),elem.clear()则代码速度将提高约10%,但内存将增加约10倍。lxml.etree与elem.clear()变体一起使用时,性能与之相同,cElementTree但消耗的内存(500MB)是它的20(root.clear())/ 2(elem.clear())倍。