Jer*_*rks 57 python xml performance parsing
我目前正在根据Python Cookbook的第12.5章运行以下代码:
from xml.parsers import expat
class Element(object):
def __init__(self, name, attributes):
self.name = name
self.attributes = attributes
self.cdata = ''
self.children = []
def addChild(self, element):
self.children.append(element)
def getAttribute(self,key):
return self.attributes.get(key)
def getData(self):
return self.cdata
def getElements(self, name=''):
if name:
return [c for c in self.children if c.name == name]
else:
return list(self.children)
class Xml2Obj(object):
def __init__(self):
self.root = None
self.nodeStack = []
def StartElement(self, name, attributes):
element = Element(name.encode(), attributes)
if self.nodeStack:
parent = self.nodeStack[-1]
parent.addChild(element)
else:
self.root = element
self.nodeStack.append(element)
def EndElement(self, name):
self.nodeStack.pop()
def CharacterData(self,data):
if data.strip():
data = data.encode()
element = self.nodeStack[-1]
element.cdata += data
def Parse(self, filename):
Parser = expat.ParserCreate()
Parser.StartElementHandler = self.StartElement
Parser.EndElementHandler = self.EndElement
Parser.CharacterDataHandler = self.CharacterData
ParserStatus = Parser.Parse(open(filename).read(),1)
return self.root
Run Code Online (Sandbox Code Playgroud)
我正在处理大小约1 GB的XML文档.有谁知道解析这些更快的方法?
Ste*_*een 65
我看起来好像你不需要程序中的任何DOM功能.我会先使用(c)ElementTree库.如果使用cElementTree模块的iterparse函数,则可以通过xml工作并在事件发生时处理它们.
但请注意,Fredriks建议使用cElementTree iterparse函数:
要解析大文件,您可以在处理完元素后立即删除元素:
for event, elem in iterparse(source):
if elem.tag == "record":
... process record elements ...
elem.clear()
Run Code Online (Sandbox Code Playgroud)
上述模式有一个缺点; 它不会清除根元素,因此您最终会得到一个包含许多空子元素的元素.如果您的文件很大,而不是很大,这可能是个问题.要解决这个问题,您需要掌握根元素.最简单的方法是启用启动事件,并保存对变量中第一个元素的引用:
# get an iterable
context = iterparse(source, events=("start", "end"))
# turn it into an iterator
context = iter(context)
# get the root element
event, root = context.next()
for event, elem in context:
if event == "end" and elem.tag == "record":
... process record elements ...
root.clear()
Run Code Online (Sandbox Code Playgroud)
该lxml.iterparse()不允许这样.
我建议你使用lxml,它是libxml2库的python绑定,非常快.
根据我的经验,libxml2和expat具有非常相似的性能.但我更喜欢libxml2(和python的lxml),因为它似乎更积极地开发和测试.libxml2还有更多功能.
lxml主要与xml.etree.ElementTree API兼容.并且其网站上有很好的文档.
注册回调会极大地减慢解析速度。[EDIT]这是因为(快速)C代码必须调用速度不如C的python解释器。基本上,您正在使用C代码(快速)读取文件,然后在Python中构建DOM (慢)。[/ EDIT]
尝试使用xml.etree.ElementTree,它在C中100%实现,并且可以解析XML而没有对python代码的任何回调。
解析文档后,您可以对其进行过滤以获取所需的内容。
如果那仍然太慢并且您不需要DOM,则另一个选择是将文件读入字符串并使用简单的字符串操作来处理它。
如果您的应用程序对性能敏感并且可能会遇到大文件(如您所说,> 1GB),那么我强烈建议不要使用您在问题中显示的代码,原因很简单,它将整个文档加载到 RAM 中. 我鼓励您重新考虑您的设计(如果可能的话)以避免将整个文档树一次保存在 RAM 中。不知道您的应用程序的要求是什么,除了尝试使用“基于事件”设计的一般建议之外,我无法正确建议任何特定方法。
| 归档时间: |
|
| 查看次数: |
58328 次 |
| 最近记录: |