如何使用python解析超大XML文档

 我来答
龙氏风采
2016-12-19 · 知道合伙人互联网行家
龙氏风采
知道合伙人互联网行家
采纳数:5849 获赞数:12819
从事互联网运营推广,5年以上互联网运营推广经验,丰富的实战经

向TA提问 私信TA
展开全部
  在工作时最有吸引力的地方在于可以尽量避免使用昔日的技术。主机、租用线路、COBOL语言......没有人应该要处理这些东西了,对不对?不幸的是,你最终会与现实发生冲突,即使是2014年,大家都知道JSON是最好的方式,你的票务供应商(你无法控制的)会告诉你,只有使用XML导出才能让大容量的数据输出他们的系统。
  唉~~~~,好,很好,无所谓。这只是一次性的事情,我不需要照顾和养活这个XML,我只需要解析它并将数据保存到Postgres中,我们就可以利用它。不应该太困难,我需要写一点python脚本…
  import xml.etree.cElementTree as ET
  tree = ET.parse('huge.xml')
  for ticket_node in tree.findall('ticket'):
  #etc...
  ......这将工作的非常好,如果我们谈论的是一个几MB的XML文档,但是如果遇到的是huge.xml它是1.3GB的巨大文档,这种方法只会融化你的笔记本电脑(以16GB的MacBookPro,一旦python的过程花了超过约3GB的内存,系统变得几乎完全反应迟钝,并且它几乎还没有完成)。回到原点。
  首先让我们快速浏览一下我们的数据。
  <?xml version="1.0" encoding="UTF-8"?>
  <tickets report_date="20140217">
  <ticket>
  <!-- various ticket fields, some of which I want -->
  <comments type="array">
  <comment>
  <!-- various comment fields, some of which I want -->
  </comment>
  <!-- possibly more comment tags -->
  </comments>
  </ticket>
  <!-- many, many ticket tags -->
  </tickets>
  不是很复杂,作为一个整体它不是一个真正的文件中,<ticket>节点只是一个列表,每一类又是一个小文件,我想挑出几部分出来。我不需要做针对树的任何复杂的遍历,只是希望从每个<ticket>节点获得一些数据然后把它扔掉再读下一个。原来ElementTree的对眼前这个场景提供了一个工具:iterparse()。让我们再试一次:
  import xml.etree.cElementTree as ET
  for event, element in ET.iterparse('huge.xml'):
  if event == 'end' and element.tag == 'ticket':
  #process ticket...
  …什么? !我的笔记本电脑又融化了!跟parse-the-whole-file的方法一样使用了完全相同的内存(和系统响应能力)。到底发生了什么事?
  好吧,稍微google了一下,google告诉我,当iterparse()读取元素时,它仍然是在内存中建立了一个完整的文档树,就像我一开始使用parse()方法一样。几个博客和stackoverflow的答案推荐添加element.clear()方法在循环结束时清理你不需要的对象,可以限制内存消耗。我拯救了你的麻烦:它不工作。其他博客,so的答案,甚至一个IBM白皮书表明需要在循环结束时进行更彻底的清扫工作结束:
  import lxml.etree as ET #the IBM piece used lxml but I tried cElementTree also
  for event, element in ET.iterparse('huge.xml'):
  if event == 'end' and element.tag == 'ticket':
  #process ticket...
  element.clear()
  while elem.getprevious() is not None:
  del elem.getparent()[0]
  ......哎呀!我溶化了另一台笔记本电脑!
  为什么不工作?坦率地说,我不知道。
  我稍微离题一下来说说为什么我爱Python。作为一个DBA和系统工程师,我面对着大量的一次性编程挑战。移动这个从这里到那里、Munge数据、将数据从这里迁移到哪里。这种类型的挑战是非常适合于蛮力编程解决问题的这种方式。总之,有时是不值得在建立一个优雅的、易于维护的解决方案上花费任何时间。有时候,你只需要解决这个问题,然后忘掉它。 在处理这类问题上Python最棒的,简洁的语法、良好的设计理念、丰富的库都有助于这个工具,很容易快速解决您碰到的任何问题。即使速度比同等的Java解决方案的10倍还慢,如果需要5分钟的时间写而不是5小时,我更愿意使用python,因为人类工时比CPU工时更有价值。
  所有这一切都证明下述方式解决了我的问题,而不会融化的笔记本电脑:
  import xml.etree.cElementTree as ET
  def process_buffer(buf):
  tnode = ET.fromstring(buf)
  #pull it apart and stick it in the database
  inputbuffer = ''
  with open('huge.xml','rb') as inputfile:
  append = False
  for line in inputfile:
  if '<ticket>' in line:
  inputbuffer = line
  append = True
  elif '</ticket>' in line:
  inputbuffer += line
  append = False
  process_buffer(inputbuffer)
  inputbuffer = None
  del inputbuffer #probably redundant...
  elif append:
  inputbuffer += line
  不是最优雅,或有效率,或者通用的解决方案,但它可以工作。刚刚看了手边的手册,利用其结构的简单性,在解析之前根据xml文件的内容将它切成可管理的块,然后解析和处理每个块,终于可以确保不再需要更长的时间来把它全部处理完。
玩转数据处理
2016-12-19 · 数据处理,Python,dotnet
玩转数据处理
采纳数:1613 获赞数:3794

向TA提问 私信TA
展开全部
超大 xml 文档在哪呢?
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 1条折叠回答
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式