3

我使用 Python 的内置 XML 解析器来加载 1.5 gig XML 文件,这需要一整天。

from xml.dom import minidom
xmldoc = minidom.parse('events.xml')

我需要知道如何进入其中并衡量其进度,以便显示进度条。有任何想法吗?

minidom 有另一种称为 parseString() 的方法,它返回一个 DOM 树,假设您传递的字符串是有效的 XML,如果我自己将文件拆分成块并一次将它们传递给 parseString,我可以合并所有DOM 树最终会重新组合在一起吗?

4

4 回答 4

5

您是否考虑过使用其他解析 XML 的方法?构建如此大的 XML 文件的树总是很慢并且占用大量内存。如果您不需要内存中的整个树,则基于流的解析会快得多。如果您习惯于基于树的 XML 操作,这可能有点令人生畏,但它会以巨大的速度提高(几分钟而不是几小时)的形式付出代价。

http://docs.python.org/library/xml.sax.html

于 2009-06-16T14:57:35.883 回答
5

您的用例要求您使用 sax 解析器而不是 dom,dom 将所有内容加载到内存中,sax 将逐行解析,并且您根据需要编写事件处理程序,这样可能是有效的,您也可以编写进度指示器

我还建议有时尝试 expat 解析器,它非常有用 http://docs.python.org/library/pyexpat.html

使用萨克斯的进步:

当 sax 以增量方式读取文件时,您可以用自己的文件对象包装您传递的文件对象,并跟踪已读取了多少。

编辑:我也不喜欢自己拆分文件并最终加入 DOM,这样你最好编写自己的 xml 解析器,我建议改用 sax 解析器我也想知道你在 DOM 树中读取 1.5 gig 文件的目的是什么? 看起来萨克斯在这里会更好

于 2009-06-16T15:10:21.787 回答
3

对于 PyGTK,而不是 PyQt,我使用 pulldom api 有一些非常相似的东西。它使用 Gtk 空闲事件(因此 GUI 不会锁定)和 Python 生成器(以保存解析状态)一次调用一点。

def idle_handler (fn):
  fh = open (fn)  # file handle
  doc = xml.dom.pulldom.parse (fh)
  fsize = os.stat (fn)[stat.ST_SIZE]
  position = 0

  for event, node in doc:
    if position != fh.tell ():
      position = fh.tell ()
      # update status: position * 100 / fsize

    if event == ....

    yield True   # idle handler stays until False is returned

 yield False

def main:
  add_idle_handler (idle_handler, filename)
于 2009-06-16T15:09:39.450 回答
2

最后合并树将非常容易。您可以只创建一个新的 DOM,然后将各个树一一添加到它上面。这也可以让您对解析的进度进行非常精细的控制。如果需要,您甚至可以通过生成不同的进程来解析每个部分来并行化它。您只需要确保智能地拆分它(而不是在标签中间拆分等)。

于 2009-06-16T14:35:52.793 回答