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)