Linux中国 Linux中国门户站!
设为主页 设为主页
收藏本站 收藏本站
 
当前位置 :首页 ->Linux技术 ->Linux程序设计 ->正文

Linux编程之序列化存储Python对象(下)

来源: 作者: 时间:2007-04-11 点击: [收藏] [投稿]

类实例

与 pickle 简单对象类型相比,pickle 类实例要多加留意。这主要由于 Python 会 pickle 实例数据(通常是 _dict_ 属性)和类的名称,而不会 pickle 类的代码。当 Python unpickle 类的实例时,它会试图使用在 pickle 该实例时的确切的类名称和模块名称(包括任何包的路径前缀)导入包含该类定义的模块。另外要注意,类定义必须出现在模块的最顶层,这意味着它们不能是嵌套的类(在其它类或函数中定义的类)。

当 unpickle 类的实例时,通常不会再调用它们的 _init_() 方法。相反,Python 创建一个通用类实例,并应用已进行过 pickle 的实例属性,同时设置该实例的 _class_ 属性,使其指向原来的类。

对 Python 2.2 中引入的新型类进行 unpickle 的机制与原来的略有不同。虽然处理的结果实际上与对旧型类处理的结果相同,但 Python 使用 copy_reg 模块的 _reconstructor() 函数来恢复新型类的实例。

如果希望对新型或旧型类的实例修改缺省的 pickle 行为,则可以定义特殊的类的方法 _getstate_() 和 _setstate_(),在保存和恢复类实例的状态信息期间,Python 会调用这些方法。在以下几节中,我们会看到一些示例利用了这些特殊的方法。

现在,我们看一个简单的类实例。首先,创建一个 persist.py 的 Python 模块,它包含以下新型类的定义:

  class Foo(object):
  
  def __init__(self, value):
  self.value = value
  

清单 11. 新型类的定义

现在可以 pickle Foo 实例,并看一下它的表示:

  >>> import cPickle as pickle
  >>> from Orbtech.examples.persist import Foo
  >>> foo = Foo('What is a Foo?')
  >>> p = pickle.dumps(foo)
  >>> print p
  ccopy_reg
  _reconstructor
  p1
  (cOrbtech.examples.persist
  Foo
  p2
  c__builtin__
  object
  p3
  NtRp4
  (dp5
  S'value'
  p6
  S'What is a Foo?'
  sb.
  >>>
  

清单 12. pickle Foo 实例

可以看到这个类的名称 Foo 和全限定的模块名称 Orbtech.examples.persist 都存储在 pickle 中。如果把这个实例 pickle 成一个文件,稍后再 unpickle 它或在另一台机器上 unpickle,则 Python 会试图导入 Orbtech.examples.persist 模块,如果不能导入,则会抛出异常。如果重命名该类和该模块或者把该模块移到另一个目录,则也会发生类似的错误。

这里有一个 Python 发出错误消息的示例,当我们重命名 Foo 类,然后试图装入先前进行过 pickle 的 Foo 实例时会发生该错误:

  >>> import cPickle as pickle
  >>> f = file('temp.pkl', 'r')
  >>> foo = pickle.load(f)
  Traceback (most recent call last):
  File "", line 1, in ?
  AttributeError: 'module' object has no attribute 'Foo'
  

清单 13. 试图装入一个被重命名的 Foo 类的经过 pickle 的实例

在重命名 persist.py 模块之后,也会发生类似的错误:

  >>> import cPickle as pickle
  >>> f = file('temp.pkl', 'r')
  >>> foo = pickle.load(f)
  Traceback (most recent call last):
  File "", line 1, in ?
  ImportError: No module named persist
  

清单 14. 试图装入一个被重命名的 persist.py 模块的经过 pickle 的实例

我们会在下面模式改进这一节提供一些技术来管理这类更改,而不会破坏现有的 pickle。

 如果您对本文有任何疑问或者建议,请到讨论区发表您的意见: >> 论坛入口 <<



上一篇:Linux编程之序列化存储Python对象(上)   下一篇:Linux设备驱动编程之阻塞与非阻塞

文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【我要投稿】 【论坛讨论
更多相关文章
Power by linux-cn.com 粤ICP备05006655号