为了账号安全,请及时绑定邮箱和手机立即绑定

对大型XML文件使用Python Iterparse

对大型XML文件使用Python Iterparse

侃侃尔雅 2019-09-21 14:33:22
我需要用Python编写一个解析器,该解析器可以在没有太多内存(只有2 GB)的计算机上处理一些非常大的文件(> 2 GB)。我想在lxml中使用iterparse做到这一点。我的文件格式为:<item>  <title>Item 1</title>  <desc>Description 1</desc></item><item>  <title>Item 2</title>  <desc>Description 2</desc></item>到目前为止,我的解决方案是:from lxml import etreecontext = etree.iterparse( MYFILE, tag='item' )for event, elem in context :      print elem.xpath( 'description/text( )' )del context但是,不幸的是,此解决方案仍在消耗大量内存。我认为问题在于,在与每个“ ITEM”打交道之后,我需要做一些清理空孩子的事情。在处理完数据以进行适当清理之后,谁能提出一些建议以解决我的问题?
查看完整描述

3 回答

?
隔江千里

TA贡献1906条经验 获得超10个赞

iterparse()让您在构建树时做些事情,这意味着除非您删除不再需要的树,否则最终还是会剩下整个树。


欲了解更多信息:阅读这个由最初的ElementTree实现的作者(但它也适用限于lxml)


查看完整回答
反对 回复 2019-09-21
?
万千封印

TA贡献1891条经验 获得超3个赞

以我的经验,有或没有element.clear(请参阅F. Lundh和L. Daly)的iterparse 不能总是处理非常大的XML文件:它运行良好一段时间,突然内存消耗飞速上升,并且发生内存错误或系统崩溃。如果遇到相同的问题,也许可以使用相同的解决方案:expat解析器。另请参见F. Lundh或以下使用OP的XML代码段的示例(另加两个表示检查是否存在编码问题的文字):


import xml.parsers.expat

from collections import deque


def iter_xml(inpath: str, outpath: str) -> None:

    def handle_cdata_end():

        nonlocal in_cdata

        in_cdata = False


    def handle_cdata_start():

        nonlocal in_cdata

        in_cdata = True


    def handle_data(data: str):

        nonlocal in_cdata

        if not in_cdata and open_tags and open_tags[-1] == 'desc':

            data = data.replace('\\', '\\\\').replace('\n', '\\n')

            outfile.write(data + '\n')


    def handle_endtag(tag: str):

        while open_tags:

            open_tag = open_tags.pop()

            if open_tag == tag:

                break


    def handle_starttag(tag: str, attrs: 'Dict[str, str]'):

        open_tags.append(tag)


    open_tags = deque()

    in_cdata = False

    parser = xml.parsers.expat.ParserCreate()

    parser.CharacterDataHandler = handle_data

    parser.EndCdataSectionHandler = handle_cdata_end

    parser.EndElementHandler = handle_endtag

    parser.StartCdataSectionHandler = handle_cdata_start

    parser.StartElementHandler = handle_starttag

    with open(inpath, 'rb') as infile:

        with open(outpath, 'w', encoding = 'utf-8') as outfile:

            parser.ParseFile(infile)


iter_xml('input.xml', 'output.txt')

input.xml中:


<root>

    <item>

    <title>Item 1</title>

    <desc>Description 1ä</desc>

    </item>

    <item>

    <title>Item 2</title>

    <desc>Description 2ü</desc>

    </item>

</root>

output.txt的:


Description 1ä

Description 2ü


查看完整回答
反对 回复 2019-09-21
  • 3 回答
  • 0 关注
  • 1188 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信