有没有人知道在Python中生成非常大的xml文件(例如100-500 MiB)的内存有效方法?
我一直在使用 lxml ,但内存使用情况仍然存在。
答案 0 :(得分:8)
也许您可以使用模板引擎而不是自己生成/构建xml?
例如,Genshi是基于xml的,并支持流输出。一个非常基本的例子:
from genshi.template import MarkupTemplate
tpl_xml = '''
<doc xmlns:py="http://genshi.edgewall.org/">
<p py:for="i in data">${i}</p>
</doc>
'''
tpl = MarkupTemplate(tpl_xml)
stream = tpl.generate(data=xrange(10000000))
with open('output.xml', 'w') as f:
stream.render(out=f)
可能需要一段时间,但内存使用量仍然很低。
Mako模板引擎(不是“本机”xml)的相同示例,但速度要快得多:
from mako.template import Template
from mako.runtime import Context
tpl_xml = '''
<doc>
% for i in data:
<p>${i}</p>
% endfor
</doc>
'''
tpl = Template(tpl_xml)
with open('output.xml', 'w') as f:
ctx = Context(f, data=xrange(10000000))
tpl.render_context(ctx)
最后一个例子在我的笔记本电脑上运行了大约20秒,产生了一个(无可否认的非常简单)151 MB xml文件,完全没有内存问题。 (根据Windows任务管理器,它保持不变大约10MB)
根据您的需要,这可能是比使用SAX等更友好,更快捷的生成xml的方法...查看文档以了解您可以使用这些引擎做什么(还有其他人,我刚刚选出这两个例子)
答案 1 :(得分:2)
生成如此大的XML文件的唯一合理方法是逐行,这意味着在运行状态机时进行打印,以及批次测试。
答案 2 :(得分:2)
显然,你必须避免在内存中构建整个树(无论是DOM还是etree或其他)。但最好的方法取决于数据的来源以及输出结构的复杂性和相互关联性。
如果它很大,因为它有数千个相当独立的项目实例,那么你可以生成外层包装器,然后为每个项目构建树,然后将每个片段序列化到输出。
如果碎片不那么独立,那么你需要做一些额外的簿记 - 比如管理生成的数据库和数据库。 IDREFS。
我会把它分成2或3个部分:一个sax事件生成器,一个输出序列化器 吃sax事件,并且可选地,如果看起来更容易使用一些独立的部分作为对象或树,那么构建这些对象然后将它们转换为序列化器的sax事件。
也许你可以将它全部作为直接文本输出来管理,而不是处理sax事件:这取决于它的复杂程度。
这也可能是使用python生成器作为流式输出的一种方式而不必在内存中构建大型结构的好地方。
答案 3 :(得分:0)
如果您的文档非常规则(例如一堆数据库记录,所有格式都相同),您可以使用我自己的“xe”库。
http://home.avvanta.com/~steveha/xe.html
xe库设计用于生成联合供稿(Atom,RSS等),我认为它易于使用。我需要为Python 2.6更新它,我还没有,抱歉。