我正在努力获得在Python 2 / Django中构建大型XML文件的最佳性能。
最终的XML文件是~500mb。使用的第一种方法是 lxml ,但花了3.5小时。我使用 xml.sax(XMLGenerator)进行了测试,花了大约相同的时间,3.5小时。
我正在尝试以最少的内存消耗找到最快的方法。我搜索了几天找到最好的解决方案但没有成功。
lxml代码:
from lxml import etree
tree_var = etree.Element("tree_var", version='1.2')
DATE = etree.SubElement(DATETIME, "DATE")
DATE.text = datetime.date.today().strftime('%Y-%m-%d')
products = FromModel.objects.all().values_list('product_id')
for product in products:
if product.state == 'new':
ARTICLE = etree.SubElement(tree_var, "ARTICLE", mode=product.state)
XMLGenerator代码:
from xml.sax.saxutils import XMLGenerator
from xml.sax.xmlreader import AttributesNSImpl
with open("tmp/" + filename + ".xml", 'wb') as out:
g = XMLGenerator(out, encoding='utf-8')
g.startDocument()
def start_tag(name, attr={}, body=None, namespace=None):
attr_vals = {}
attr_keys = {}
for key, val in attr.iteritems():
key_tuple = (namespace, key)
attr_vals[key_tuple] = val
attr_keys[key_tuple] = key
attr2 = AttributesNSImpl(attr_vals, attr_keys)
g.startElementNS((namespace, name), name, attr2)
if body:
g.characters(body)
def end_tag(name, namespace=None):
g.endElementNS((namespace, name), name)
def tag(name, attr={}, body=None, namespace=None):
start_tag(name, attr, body, namespace)
end_tag(name, namespace)
g.endDocument()
我非常确定xml.sax正在使用更少的内存,并且它实时增加了文件。另一方面,lxml只使用一个巨大的缓冲区在循环结束时创建文件。
任何寻求帮助的想法?
谢谢!
答案 0 :(得分:0)
阅读时,您可能仍在加载整个输入文件。您可以尝试下面的行,以获取逐步读取文件的示例。 This stackoverflow问题还提供了比下面的代码段更多的上下文。您还可以在iterparse()
中指定目标元素,以便可以一次转储整个目标元素。
for event, elem in etree.iterparse(in_file, events=('start', 'end',)):
if event == 'start':
start_tag(elem.tag, {}, elem.text)
elif event == 'end':
end_tag(elem.tag)
# It's safe to call clear() here because no descendants will be accessed
elem.clear()
# Also eliminate now-empty references from the root node to elem
while elem.getprevious() is not None:
del elem.getparent()[0]