2

我正在处理大小约为 85MB 的 XML 文件。目前我只是想处理一个。我正在做的是下载一个 zip,解压缩到磁盘,然后将 XML 转换为 Python Dict,更改一些内容,然后保存 Dict,并将其发送到 MongoDB。除非我要转换为 Python 字典,否则进程会冻结/消失..

我在具有 Ubuntu 13.04 服务器、4 个 2.6 核、16GB 内存和 1TB 15,000RPM 的 VM 上运行此脚本。我正在监视脚本运行时,基本上 python 在 7 分钟内占用了 12% 的 RAM,然后消失了,进程从我的高使用率列表中掉下来,我从终端的管道只是不动。我用 CTRL+Z 杀死它并返回"Write failed: Broken pipe"

终端上打印的最后一件事是"Converting dailyprice_0505_eur.xml.zip",这让我怀疑 xmltodict 可能有什么问题,但老实说我被卡住了。带有数据的示例代码应该适用于任何愿意帮助我测试的人。任何帮助表示赞赏!谢谢。

#Importing
import urllib, xmltodict, os
from zipfile import ZipFile

#Getting Working Dir
abspath = os.path.abspath(__file__)
root = os.path.dirname(abspath) + "/"
print "Current Working Directory: " + root

#Defining
urlAuth = 'https://dl.dropboxusercontent.com/u/9235267/'
dailypriceFL = ['dailyprice_0505_eur.xml.zip']
dailyPriceDict = {}

for x in dailyPriceFL:
    print '  * Downloading',x
    urllib.urlretrieve(urlAuth+x, x)

    print '  * Extracting',x
    with ZipFile(x, "r") as z:
        z.extractall(root)

    print '  * Converting',x
    f = open(root+x.replace(".zip",""))
    data = xmltodict.parse(f.read())
    f.close()

    print '  * Adding Currency to Dict',x
    for y in data['prices']['price']:
        y.update({"currency": x[-7:].replace(".xml","").upper()})

    print '  * Ammending',x
    dailyPriceDict.update(data)

    print '  * Deleting',x
    os.remove(root+x)
    os.remove(root+x.replace(".zip",""))
    print '  * Finished',x
4

1 回答 1

0

尽管您列出了规格,我想知道这是否不是内存错误。当我尝试加载您的 XML 时,xml.dom.minidom我得到了这个:

Traceback (most recent call last):
  File "c:\python27\lib\xml\dom\minidom.py", line 1930, in parseString
    return expatbuilder.parseString(string)
  File "c:\python27\lib\xml\dom\expatbuilder.py", line 940, in parseString
    return builder.parseString(string)
  File "c:\python27\lib\xml\dom\expatbuilder.py", line 223, in parseString
    parser.Parse(string, True)
  File "c:\python27\lib\xml\dom\expatbuilder.py", line 751, in start_element_handler
    node = minidom.Element(qname, uri, prefix, localname)
  File "c:\python27\lib\xml\dom\minidom.py", line 653, in __init__
    self._attrs = {}   # attributes are double-indexed:
MemoryError

不过,这似乎确实对我有用:

>>> import xmltodict, os
>>> data = open('price.xml').read()
>>> xml = xmltodict.parse(data)
>>> xml['prices']['price'][0]
OrderedDict([(u'code', u'AD1550.301.1'), 
             (u'startdate', u'2013-08-24'), 
             (u'enddate', u'2013-09-30'), 
             (u'rentalprice', u'126.00'), 
             (u'midweekrentalprice', u'0.00'), 
             (u'weekendrentalprice', u'0.00'), 
             (u'fixprice', u'0.00')])

这在我的系统上确实占用了近 800Mb,但我似乎没有出错。但是,如果我在尝试使用 minidom尝试将其解析为xmltodict,我会得到类似这样的结果:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "c:\python27\lib\site-packages\xmltodict.py", line 228, in parse
    parser.Parse(xml_input, True)
xml.parsers.expat.ExpatError: out of memory: line 1, column 0

这直接表明,因为两者都基于 ,所以在expat脚本运行(或循环的迭代)之间没有释放一些东西,你需要以某种方式重构。

于 2013-08-28T22:30:08.907 回答