类型错误保存搁置中的lxml元素

时间:2015-02-09 16:27:54

标签: python lxml pickle

我正在处理一些xml文件 pb_id是一个字符串 page_elements是一个列表。

pb_id = x.xpath('//pb/@xml:id')[0]
page_elements = x.xpath('//@xml:id[preceding::pb]')

我想将这些值保存在搁置缓存中:

s = shelve.open('cache.shelve')
s[str(pb_id)] = page_elements

但它会返回此错误:

  

无法挑选_Element对象

我是否需要将page_elements转换为其他类型? type(page_elements)<type 'list'>

2 个答案:

答案 0 :(得分:1)

只有可选择的数据类型可以存储在一个架子中 - 特别是,C扩展添加的类型需要显式支持才能被选择;到目前为止,lxml还没有写过支持。

除非您愿意为上游lxml提供补丁并通过合并和发布来管理它,否则我建议您重新审视您的要求:为什么要尝试存储有问题的数据?您能否以不同的方式(例如,XML文本 - 即使该文本被搁置)序列化内容,并在加载时反序列化它?

如果将XML元素封装在您控制的数据结构中,则可以覆盖__getstate__()__setstate__()以适当地序列化和反序列化;请阅读the pickle library documentation了解详情。

你最终可能会遇到这样的事情:

class PicklablePage(object):
  def __init__(self, page_elements=None):
    self.page_elements = page_elements or []
  def __getstate__(self):
    return {'page_elements': [ lxml.etree.tostring(el)
                               for el in self.page_elements ]}
  def __setstate__(self, state):
    self.page_elements = [ lxml.etree.fromstring(el_text)
                           for el_text in state['page_elements'] ]

然后可以安全地对其进行酸洗和去除(因此搁置和取消搁置):

>>> el = lxml.etree.fromstring('<content>Hello</content>')
>>> p = PicklablePage([el])
>>> print pickle.loads(pickle.dumps(p)).page_elements[0].text
Hello

答案 1 :(得分:1)

好的,明白了:列表是由_Element对象组成的。 我想我已经解决了这个问题,将所有列表元素转换为str()

 page_elements[:] = [str(x) for x in page_elements]