3

大きな XML ドキュメントを処理する必要があるスクリプトのメモリ フットプリントを削減するために、iterparse を試してきました。これが例です。TMX ファイルを読み取り、ユーザーが指定したサイズを超えないように 1 つまたは複数の出力ファイルに分割するために、この単純なスクリプトを作成しました。iterparse を使用しているにもかかわらず、886MB のファイルを 100MB のファイルに分割すると、スクリプトは使用可能なすべてのメモリで実行されます (私の 8MB の 6.5 を使用してクロールに粉砕します)。

私は何か間違ったことをしていますか?メモリ使用量が非常に高くなるのはなぜですか?

#! /usr/bin/python
# -*- coding: utf-8 -*-
import argparse
import codecs
from xml.etree.ElementTree import iterparse, tostring
from sys import getsizeof

def startNewOutfile(infile, i, root, header):
    out = open(infile.replace('tmx', str(i) + '.tmx'), 'w')
    print >>out, '<?xml version="1.0" encoding="UTF-8"?>'
    print >>out, '<!DOCTYPE tmx SYSTEM "tmx14.dtd">'
    print >>out, roottxt
    print >>out, headertxt
    print >>out, '<body>'
    return out

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-m', '--maxsize', dest='maxsize', required=True, type=float, help='max size (in MB) of output files')
    parser.add_argument(dest='infile', help='.tmx file to be split')
    args = parser.parse_args()

    maxsize = args.maxsize * 1024 * 1024

    nodes = iter(iterparse(args.infile, events=['start','end']))

    _, root = next(nodes)
    _, header = next(nodes)

    roottxt = tostring(root).strip()
    headertxt = tostring(header).strip()

    i = 1
    curr_size = getsizeof(roottxt) + getsizeof(headertxt)
    out = startNewOutfile(args.infile, i, roottxt, headertxt)

    for event, node in nodes:
        if event =='end' and node.tag == 'tu':
            nodetxt = tostring(node, encoding='utf-8').strip()
            curr_size += getsizeof(nodetxt)
            print >>out, nodetxt
        if curr_size > maxsize:
            curr_size = getsizeof(roottxt) + getsizeof(headertxt)
            print >>out, '</body>'
            print >>out, '</tmx>'
            out.close()
            i += 1
            out = startNewOutfile(args.infile, i, roottxt, headertxt)
        root.clear()

    print >>out, '</body>'
    print >>out, '</tmx>'
    out.close()
4

1 に答える 1

6

関連する質問で答えを見つけました:なぜ elementtree.ElementTree.iterparse はそんなに多くのメモリを使用していますか?

for ループの反復ごとに root.clear() だけでなく node.clear() も必要です。ただし、開始イベントと終了イベントの両方を処理しているため、tu ノードをすぐに削除しないように注意する必要があります。

for e, node in nodes:
    if e == 'end' and node.tag == 'tu':
        nodetxt = tostring(node, encoding='utf-8').strip()
        curr_size += getsizeof(nodetxt)
        print >>out, nodetxt
        node.clear()
    if curr_size > maxsize:
        curr_size = getsizeof(roottxt) + getsizeof(headertxt)
        print >>out, '</body>'
        print >>out, '</tmx>'
        out.close()
        i += 1
        out = startNewOutfile(args.infile, i, roottxt, headertxt)
    root.clear()
于 2014-08-05T06:06:15.030 に答える