Python - 大型XML到JSON到文件/ RAM和交换过载

问题描述 投票:2回答:2

我目前正致力于通过OpenStreetMaps省/州转储创建一种Pythonic解析方式;据我所知,只知道如何处理非常大的XML文件(对吧?)。

我目前正在使用lxml etree iterparse模块来解析dumps for the Province of Quebec(quebec-latest.osm.bz2)。我想拉任何有高速公路信息的条目,转换为JSON,保存到文件,并刷新,虽然它似乎没有工作。

我目前正在运行i7-4770,16GB的RAM,128GB的SSD和OSX 10.9。当我启动下面的代码时,我的RAM会在几秒钟内完全填满,并在30秒内完成交换。之后我的系统将要求我关闭应用程序以腾出空间,或最终冻结。

这是我的代码;你会注意到那里很可能有很多糟糕的/加密代码,但是我已经到了能够插入任何我能找到的东西的地步,希望它可以工作。非常感谢任何帮助。谢谢!

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from lxml import etree
import xmltodict, json, sys, os, gc

hwTypes = ['motorway', 'trunk', 'primary', 'secondary', 'tertiary', 'pedestrian', 'unclassified', 'service']

#Enable Garbadge Collection
gc.enable()

def processXML(tagType):

    f = open('quebecHighways.json', 'w')
    f.write('[')
    print 'Processing '
    for event, element in etree.iterparse('quebec-latest.osm', tag=tagType):
        data = etree.tostring(element)
        data = xmltodict.parse(data)
        keys = data[tagType].keys()
        if 'tag' in keys:
            if isinstance(data[tagType]['tag'], dict):
                if data[tagType]['tag']['@k'] == 'highway':
                    if data[tagType]['tag']['@v'] in hwTypes:
                        f.write(json.dumps(data)+',')
                        f.flush() #Flush Python
                        os.fsync(f.fileno()) #Flush System
                        gc.collect() #Garbadge Collect
            else:
                for y in data[tagType]['tag']:
                    if y['@k'] == 'highway':
                        if y['@v'] in hwTypes:
                            f.write(json.dumps(data)+',')
                            f.flush()
                            os.fsync(f.fileno())
                            gc.collect()
                            break

        #Supposedly there is supposed to help clean my RAM.
        element.clear()
        while element.getprevious() is not None:
            del element.getparent()[0]

    f.write(']')
    f.close()
    return 0

processXML('way')
python xml json lxml openstreetmap
2个回答
0
投票

xmltodict存储在内存中生成的字典,因此如果您的数据字典很大,那么这样做并不是一个好主意。仅使用iterparse会更有效率。

另一种选择可能是使用xmltodict提供的流媒体可能性。更多信息在http://omz-software.com/pythonista/docs/ios/xmltodict.html


0
投票

我会说你的生活比必要的更复杂。你有效地反复将整个子树转储到xmltodict并使其一次又一次地解析整个子树。

如果我是你,我会抛弃xmltodict,坐在你的后面,阅读一两个教程,并使用标准的东西:xml.sax(如果你不需要太多的跳跃,那真的不是那么困难;只是工作在converting Bible)或iterparse并使用它。它真的不那么复杂。

© www.soinside.com 2019 - 2024. All rights reserved.