【发布时间】:2018-03-13 11:51:59
【问题描述】:
我正在尝试获得在 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 仅在循环结束时创建文件,使用巨大的缓冲区。
有什么建议吗?
谢谢!
【问题讨论】:
-
看看这个docs.djangoproject.com/en/2.0/howto/outputting-csv/… 我知道 csv 文件,但你可以更改 xml 文件的内容
-
看看
XMLGenerator类。您可以找到如何使用它的示例here。 -
@Reidel:好的,我会检查那个。谢谢我用我的代码示例更新了我的线程。
-
另一个资源可能有用d.cxcore.net/Python/Python_Cookbook_3rd_Edition.pdf 并查看
CHAPTER 12 Concurrency中的12.8. Performing Simple Parallel Programming部分 -
感谢@Reidel 的提示我创建了一个新代码,其中我从 3h30 改进到不到 1 小时(使用 8 核和 2 核测试)。他来了:
import codecs from multiprocessing.dummy import Pool, cpu_count def do_work(products): <write to file> def parallel(result=None): pool = Pool(cpu_count()-1) # to prevent GIL with codecs.open(filename.xml", 'w+', "utf-8") as fp: <do stuff> pool.map(do_work, loop_object) pool.close() pool.join() parallel()我认为它可以改善内存,但我很高兴我节省了创建 XML 的时间。
标签: python xml multiprocessing lxml concurrent.futures