在加载大文件时显示Python XML解析器的进度

3 投票
4 回答
2485 浏览
提问于 2025-04-15 12:17

我正在使用Python自带的XML解析器来加载一个1.5GB的XML文件,但这花了我整整一天的时间。

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

我想知道怎么能查看这个过程的进展,以便我可以显示一个进度条。有没有什么好主意?

minidom还有一个叫做parseString()的方法,它会返回一个DOM树,前提是你传给它的字符串是有效的XML。如果我自己把文件分成小块,然后一个一个地传给parseString,最后能把所有的DOM树合并在一起吗?

4 个回答

3

我有一个和这个很相似的例子,是用PyGTK而不是PyQt,使用的是pulldom这个接口。它是通过Gtk的空闲事件一点一点地调用的,这样就不会让图形界面卡住,同时还用到了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)
5

你有没有考虑过用其他方法来解析XML文件?处理这么大的XML文件时,构建一个树形结构总是会很慢,而且占用很多内存。如果你不需要把整个树都放在内存里,使用流式解析会快得多。虽然如果你习惯了树形结构的XML处理,可能会觉得有点难,但这样做会让速度大幅提升(从几个小时缩短到几分钟)。

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

5

你的使用场景需要用SAX解析器,而不是DOM解析器。DOM会把所有内容都加载到内存里,而SAX则是逐行解析,你可以根据需要编写事件处理程序,这样会更有效率,而且你也可以写进度指示器。

我还建议你试试Expat解析器,它非常有用。你可以查看这个链接了解更多信息:http://docs.python.org/library/pyexpat.html

关于使用SAX的进度:

因为SAX是逐步读取文件的,你可以把传入的文件对象包裹起来,这样就能跟踪已经读取了多少内容。

补充一下:我也不太喜欢自己拆分文件然后再把它们合并成DOM,这样的话不如自己写一个XML解析器。我更推荐使用SAX解析器。我也想知道你为什么要用DOM树读取1.5GB的文件?看起来SAX会更适合这种情况。

撰写回答