ElementTree で巨大な XML を処理する

ElementTree のページに書いてあることだけど、メモとして。
xml.etree.ElementTree.iterparse を使うと、DOM のようにメモリを食わず、SAX よりプログラムしやすいかと思いきや、試しに Wikipedia のダンプデータを食わしてみたら、がんがんメモりを食う。まぁ、ルートエレメントの end イベントのときに、配下のノードがすべて必要になるので当然なんだけど。で、対策は毎回ルートエレメントの配下をクリアするということらしい。
ということで、Wikipedia のデータを処理するときはこんな感じ。

import xml.etree import ElementTree

WIKIPEDIA_NAMESPACE = 'http://www.mediawiki.org/xml/export-0.3/'

class Page(object):
    __slots__ = 'title text'.split()

    def __init__(self, title, text):
        self.title = title
        self.text = text

def translate_path(path):
    return '/'.join('{%s}%s' % (WIKIPEDIA_NAMESPACE, tag) for tag in path.split('/'))

def pages(file_or_stream):
    context = ElementTree.iterparse(file_or_stream, events = ('start', 'end'))
    context = iter(context)
    event, root = iter.next()

    for event, element in context:
        if event == 'end' and element.tag == translate_path('page'):
            title = element.findtext(translate_path('title'))
            text = element.findtext(translate_path('revision/text'))
            root.clear()
            yield Page(title = title, text = text)