Python2 sax解析器,大文件的最佳速度和性能?

rap*_*ura 6 xml sax python-2.x suds

所以我一直在使用泡沫来使用网络服务,这有很大的好处。

遇到性能问题,对于某些数据,CPU 会急剧上升,需要 60 秒以上才能完成请求,该请求由gunicorn、suds 到 webservice 等提供服务。

使用 line_profiler、objgraph、memory_profiler 等进行研究,我发现罪魁祸首是解析一个 9.2mb 的 xml 文件大约需要 13 秒,这是来自 Web 服务的响应。

这不太正常吧?只有 9.2mb,我看到 99% 的时间都花在解析它上,并且解析是通过“from xml.sax import make_parser”完成的,这意味着标准 python?

有没有更快的大文件 xml 解析器?

我将详细了解 XML 中的结构类型,但到目前为止我知道它的“UmResponse”,其中包含大约 7000 个“Document”元素,每个元素包含 10-20 行元素。

编辑:进一步调查,我发现 13 秒的一半花费在 suds/sax/ 中的 suds 处理程序中......当然,hm 可能是 suds 问题,而不是 python 库。

EDIT2:suds unmarshaller 花费了大部分时间来处理这个问题,大约 50 秒,用 sax 解析也很慢,使用 xml.minidom 的 pysimplesoap 大约需要 13 秒和大量内存。然而 lxml.etree 低于 2 秒,objectify 也非常快,足够快,可以使用它代替 ElementTree(对于这里的特定 xml,它比 cElementTree 更快,一个 0.5 秒,另一个 0.17 秒)

解决方案:Suds 允许参数 retxml 为 true,无需解析和解组即可返回 XML,从那里我可以使用 lxml 更快地完成此操作。

rap*_*ura 4

使用 sax 进行 Suds 解析需要时间,而且 suds src 绑定/绑定中的解组方法需要花费更多时间,该方法大量使用 umx/Typed 类。

解决方案,绕过所有这些:将 retxml=True 传递给客户端,以便 suds 不会进行解析和解组,这是 suds 的绝佳选择!相反,我发现 lxml 是最快的,甚至比 cElementTree 还要快。

from lxml import objectify
from lxml.etree import XMLParser
Run Code Online (Sandbox Code Playgroud)

现在另一个问题是 xml 有巨大的 txt 节点,超过 10mb,因此 lxml 会被放弃,XMLParser 需要标志 Huge_tree=True 来吞下并处理大数据文件。像这样设置,set_element_class_lookup确实有很大的好处,没有它你就不会真正得到一个ObjectifedElement。

parser = XMLParser(remove_blank_text=True, huge_tree=True)
parser.set_element_class_lookup(objectify.ObjectifyElementClassLookup())
objectify.set_default_parser(parser)
obj = objectify.fromstring(ret_xml)
# iter here and return Body or Body[0] or whatever you need
#so all code which worked with suds unmarshaller works with objectified aswell 
Run Code Online (Sandbox Code Playgroud)

然后,当 suds 解组时按属性查找元素的其余代码工作正常(就在返回肥皂信封的正文之后),无需为 xpath 或 iteraparse xml 元素烦恼。

objectify 在 1-2 秒内完成工作,而肥皂水解组需要 50-60 秒。