python – 无法将lxml etree对象传递给单独的进程
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python – 无法将lxml etree对象传递给单独的进程,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3296字,纯文字阅读大概需要5分钟。
内容图文
![python – 无法将lxml etree对象传递给单独的进程](/upload/InfoBanner/zyjiaocheng/968/4a2f634084a444c2a98b4f1de865815e.jpg)
我正在研究一个项目,使用lxml在python中同时解析多个xml文件.当我初始化进程时,我希望我的主类在将etree对象传递给进程之前对XML做一些工作,但我发现当etree对象到达新进程时,类仍然存活但是XML已经从在对象中,getroot()返回None.
我知道我只能使用队列传递可选择的数据,但是这也是我传递给’args’字段内的进程的情况吗?
这是我的代码:
import multiprocessing, multiprocessing.pool, time
from lxml import etree
def compute(tree):
print("Start Process")
print(type(tree)) # Returns <class 'lxml.etree._ElementTree'>
print(id(tree)) # Returns new ID 44637320 as expected
print(tree.getroot()) # Returns None
def pool_init(queue):
# see https://stackoverflow.com/a/3843313/852994
compute.queue = queue
class Main():
def __init__(self):
pass
def main(self):
tree = etree.parse('test.xml')
print(id(tree)) # Returns object ID 43998536
print(tree.getroot()) #Returns <Element SymCLI_ML at 0x29f5dc8>
self.queue = multiprocessing.Queue()
self.pool = multiprocessing.Pool(processes=1, initializer=pool_init, initargs=(self.queue,))
self.pool.apply_async(func=compute, args=(tree,))
time.sleep(10)
if __name__ == '__main__':
Main().main()
任何和所有帮助非常感谢.
UPDATE / ANSWER
根据下一篇文章中的答案我已经对它进行了一些修改,并设法让它在不使用String IO的情况下使用更低的内存占用.
etree.tostring方法返回一个字节数组,可以对其进行pickle,然后取消对它的解释,字节数组可以由etree解析.
import multiprocessing, multiprocessing.pool, time, copyreg
from lxml import etree
def compute(tree):
print("Start Process")
print(type(tree)) # Returns <class 'lxml.etree._ElementTree'>
print(tree.getroot()) # Returns <Element SymCLI_ML at 0x29f5dc8>. Success!
def pool_init(queue):
# see https://stackoverflow.com/a/3843313/852994
compute.queue = queue
def elementtree_unpickler(data):
return etree.parse(BytesIO(data))
def elementtree_pickler(tree):
return elementtree_unpickler, (etree.tostring(tree),)
copyreg.pickle(etree._ElementTree, elementtree_pickler, elementtree_unpickler)
class Main():
def __init__(self):
pass
def main(self):
tree = etree.parse('test.xml')
print(tree.getroot()) #Returns <Element SymCLI_ML at 0x29f5dc8>
self.queue = multiprocessing.Queue()
self.pool = multiprocessing.Pool(processes=1, initializer=pool_init, initargs=(self.queue,))
self.pool.apply_async(func=compute, args=(tree,))
time.sleep(10)
if __name__ == '__main__':
Main().main()
更新2
在对内存进行一些基准测试后,我发现传递大型对象会导致无法通过主进程上的垃圾回收来清除对象.这可能不是小规模的问题,但是etree对象在内存中的数量级为数百MB.只要在语句中使用XML对象调用异步任务,如果从主进程中删除该对象,即使我手动调用垃圾回收,也无法从内存中清除该对象.因此,我恢复了在主进程中关闭XML并将文件名传递给子进程.
解决方法:
使用以下代码为lxml Element / ElementTree对象注册简单的pickler / unpickler.我过去用过lxml和zmq.
import copy_reg
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
from lxml import etree
def element_unpickler(data):
return etree.fromstring(data)
def element_pickler(element):
data = etree.tostring(element)
return element_unpickler, (data,)
copy_reg.pickle(etree._Element, element_pickler, element_unpickler)
def elementtree_unpickler(data):
data = StringIO(data)
return etree.parse(data)
def elementtree_pickler(tree):
data = StringIO()
tree.write(data)
return elementtree_unpickler, (data.getvalue(),)
copy_reg.pickle(etree._ElementTree, elementtree_pickler, elementtree_unpickler)
内容总结
以上是互联网集市为您收集整理的python – 无法将lxml etree对象传递给单独的进程全部内容,希望文章能够帮你解决python – 无法将lxml etree对象传递给单独的进程所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。