0

OS X (10.8.2) で lxml (3.2.0) を使用して、Python (2.7.2) で 1.6 GB の XML ファイルを解析したいと考えています。メモリ消費に関する潜在的な問題については既に読んでいたので、 fast_iterを既に使用していますが、メイン ループの後、実際の XML ファイルからのデータを保持しなくても、約 8 GB の RAM を消費します。

from lxml import etree

def fast_iter(context, func, *args, **kwargs):
    # http://www.ibm.com/developerworks/xml/library/x-hiperfparse/
    # Author: Liza Daly
    for event, elem in context:
        func(elem, *args, **kwargs)
        elem.clear()
        while elem.getprevious() is not None:
            del elem.getparent()[0]
    del context

def process_element(elem):
    pass

context = etree.iterparse("sachsen-latest.osm", tag="node", events=("end", ))
fast_iter(context, process_element)

fast_iter()要素とコンテキスト全体が削除されており、現時点では XML データを処理していないため、なぜこのような大規模なリークが発生するのかわかりません。

何か案は?

4

1 に答える 1

3

問題は の動作にありetree.iterparse()ます。要素ごとにメモリを使用するだけだと思う​​かもしれませんがnode、他のすべての要素をメモリに保持していることがわかります。それらをクリアしないため、特に .osm (OpenStreetMaps) ファイルを解析してノードを探すときに、メモリが後で爆発してしまいますが、それについては後で詳しく説明します。

私が見つけた解決策は、タグをキャッチするのではなく、nodeすべてのタグをキャッチすることでした:

context = etree.iterparse(open(filename,'r'),events=('end',))

次に、すべてのタグをクリアしますが、関心のあるタグのみを解析します。

for (event,elem) in progress.bar(context):
    if elem.tag == 'node':
        # do things here

    elem.clear()
    while elem.getprevious() is not None:
        del elem.getparent()[0]
del context

関心のある他の要素が削除される可能性があることに注意してください。必要に応じて if を追加してください。たとえば (これは .osm 固有です)tagsからネストされていますnodes

if elem.tag == 'tag':
    continue
if elem.tag == 'node':
    for tag in elem.iterchildren():
        # do stuff

後でメモリが爆発的に増加した理由は非常に興味深いものです。.osm ファイルは、最初nodes来て、ways次にrelations. etreeしたがって、コードは最初にノードで問題なく動作し、残りの要素を通過するにつれてメモリがいっぱいになります。

于 2014-08-05T09:23:56.240 に答える