11.1. picklePython 对象序列化

pickle模块实现了一个基本但功能强大的Python对象序列化和反序列化算法。"Pickling"过程藉以 Python 对象层次结构转换为字节流,和"unpickling"是藉以字节流的形式被转换回对象层次结构中的逆运算。Pickling (和 unpickling) 或者是已知的作为"序列化"、"编组" [1]或"扁平化",然而,为了避免混淆,在这里使用的术语"pickling"和"unpickling"。

本文档描述pickle模块和cPickle模块。

警告

pickle模块处理错误或恶意构造的数据时并不安全。永远不要 unpickle 来源不受信任或未经身份验证的数据。

11.1.1. Relationship to other Python modules

pickle模块有一个经过优化的变形,叫cPickle模块。正如其名称所暗示, cPickle是 C 编写的因此它可以比pickle快 1000倍。但是它不支持使用子类化的Pickler()Unpickler()类,因为在cPickle中,这些都是函数,而不是类。大多数应用程序不需要此功能,并可以受益于cPickle的改进性能。除此之外,这两个模块的接口是几乎完全相同 ;本手册中描述的通用接口和差异指出了在必要时。在下面的讨论中,我们使用术语"Pickle"总体上描述了PicklecPickle模块。

这两个模块产生的流数据保证可以互换。

Python 提供了更多原始序列化模块称为封送处理,但在一般情况下pickle总是应该序列化的 Python 对象的首选的方式。marshal的存在主要是支持 Python 的.pyc文件。

pickle模块不同于marshal在几个重要方面:

  • pickle模块跟踪的对象,它具有已被序列化,以便以后引用相同的对象不会再一次序列化。marshal不会这样做。

    这已对递归对象和对象共享的意义。递归对象是包含对自身的引用的对象。这些问题不由法警和事实上,试图封送递推对象将会崩溃你 Python 解释器。对象共享时会有不同的地方被序列化的对象层次结构中的同一对象的多个引用。pickle只有一次,用来存储这些对象,并确保所有其他引用指向的主副本。共享的对象保持共享,这可以是可变对象非常重要。

  • marshal不能用于用户定义的类和它们的实例进行序列化。pickle可以保存和透明的方式,恢复类实例,然而类定义必须是可导入并生活在同一个模块中作为对象存储时。

  • 元帅的序列化格式是不能保证可移植跨 Python 版本。因为其主要工作是支持.pyc文件,Python 执行者储备权更改序列化格式在非兼容方式需要出现。泡菜的序列化格式被保证跨 Python 版本是向后兼容。

请注意序列化是一个更加原始的概念比坚持不懈 ;虽然泡菜读取和写入文件的对象,它就不处理的持久性对象命名问题,也非持久性对象的并发访问 (甚至更复杂的) 问题。泡菜模块可以将一个复杂对象转换的字节流,它可以将字节流转换对象具有相同的内部结构。或许最明显的事情,如何处理这些字节流是把它们写到一个文件中,但它也是可以想象的跨网络发送它们或将它们存储在数据库中。搁置的模块提供一个简单的接口来腌制,unpickle 上 DBM 式数据库文件的对象。

11.1.2. Data stream format

pickle所使用的数据格式是 Python 特定的。这具有的优点是没有外部标准(例如XDR(其不能表示指针共享))施加的限制;然而,这意味着非 Python 程序可能无法重建腌渍的 Python 对象。

默认情况下,泡菜数据格式使用可打印的 ASCII 表示形式。这是稍有更多的篇幅比二进制表示形式。使用可打印的 ASCII (以及一些其他特性的泡菜表示) 的最大优点是用于调试或恢复是可能为人类使用标准文本编辑器读取的腌渍的文件。

目前有 3 种不同的协议,可以用于Pickling。

  • Protocol version 0 is the original ASCII protocol and is backwards compatible with earlier versions of Python.
  • Protocol version 1 is the old binary format which is also compatible with earlier versions of Python.
  • Protocol version 2 was introduced in Python 2.3. It provides much more efficient pickling of new-style classes.

请参阅 PEP 307的详细信息。

如果未指定一种协议,则将使用协议 0。如果协议指定为负值或HIGHEST_PROTOCOL,将使用可用的最高协议版本。

版本 2.3 中的更改:介绍了协议参数。

二进制的格式,这是效率稍高,可以选择通过指定协议版本 > = 1。

11.1.3. Usage

要序列化的对象层次结构中,您首先创建一个pickler,然后你调用pilcker的dump()方法。若要反序列化数据的流,您首先创建 unpickler,然后你叫 unpickler 的load ()方法。泡菜模块提供下列常量:

pickle.HIGHEST_PROTOCOL

最高的协议版本。此值可作为协议值传递。

新版本 2.3。

一定要始终打开的pickle文件创建与协议 > = 1 以二进制模式。为旧的基于 ASCII 的 pickle 协议 0 你可以使用文本模式或二进制模式有两种: 只要你保持一致。

书面协议 0 以二进制模式的 pickle 文件将包含孤换行符作为行终止符,并且因此将"搞笑"查看时的外观在记事本或其他不支持这种格式的编辑。

pickle模块提供以下功能,可使序列化过程更方便:

pickle.dump(obj, file[, protocol])

Obj腌的表示写入打开的文件对象文件这就相当于Pickler (文件, protocol).dump(obj)

如果省略了协议参数,则将使用协议 0。如果协议指定为负值或HIGHEST_PROTOCOL,则将使用最高的协议版本。

版本 2.3 中的更改:介绍了协议参数。

文件必须接受单个字符串参数的write ()方法。因此,它可以为写作、 一个StringIO对象或任何其他自定义的对象的符合此接口打开一个文件对象。

pickle.load(file)

从打开的文件对象文件中读取一个字符串并将其解释为pickle的数据流,重建和返回原始对象层次结构。这是相当于Unpickler(file).load()

文件必须有两种方法,其中 read ()方法需要一个 integer 参数,readline ()方法不需要参数。这两种方法应返回一个字符串。因此文件可以开放供阅读、 一个StringIO对象或满足此接口的任何其他自定义对象的文件对象。

这个函数自动确定数据流是否是二进制模式写入。

pickle.dumps(obj[, protocol])

返回该对象作为一个字符串,而不是写入一个文件的腌的代表性。

如果省略了协议参数,则将使用协议 0。如果协议指定为负值或HIGHEST_PROTOCOL,则将使用最高的协议版本。

版本 2.3 中的更改:添加了协议参数。

pickle.loads(string)

从字符串中读取腌的对象层次结构。过去的腌的对象表示字符串中的字符将被忽略。

picle模块还定义了三种例外情况:

exception pickle.PickleError

下面定义的其他例外的公共基类。这从异常继承。

exception pickle.PicklingError

在一个 unpicklable 对象被传递给dump()方法时,将引发此异常。

exception pickle.UnpicklingError

问题 unpickling 对象时,将引发此异常。请注意其他例外情况也期间可能会引发 unpickling,包括 (但不是一定局限于) AttributeError EOFError ImportError IndexError

泡菜模块还出口两个 callables [2]酸洗Unpickler

class pickle.Pickler(file[, protocol])

这需要写入将泡菜数据流的文件类似对象。

如果省略了协议参数,则将使用协议 0。如果协议指定为负值或HIGHEST_PROTOCOL,则将使用最高的协议版本。

版本 2.3 中的更改:介绍了协议参数。

文件必须接受单个字符串参数的write ()方法。因此,它可以打开的文件对象,一个StringIO对象或满足此接口的任何其他自定义对象。

施暴对象定义一个 (或两个) 的公共方法:

dump(obj)

Obj腌的表示写入打开的 file 对象的构造函数中给出。将使用二进制或 ASCII 格式,具体取决于传递给构造函数的协议参数的值。

clear_memo()

清除酸洗的"备忘录"。这份备忘录是记得的对象已经看到施暴,以便共享或腌渍由引用而不是值的递推对象的数据结构。重新使用 picklers 时,此方法很有用。

在 Python 2.3 之前clear_memo()只是由cPickle创建的 picklers 上可用。泡菜模块中,picklers 有一个实例变量,被称为是一个 Python 字典的备注所以若要清除这份备忘录的泡菜模块施暴,可以执行以下操作:

mypickler.memo.clear()

不需要支持旧版本的 Python 的代码应该只需使用clear_memo()

很可能要进行多次调用相同的酸洗系统实例的dump()方法。然后,这些必须被匹配对相同数量的对相应的Unpickler实例的load ()方法的调用。如果相同的对象腌制的由多个dump()调用, load ()将产生出对同一对象的引用。[] 3

Unpickler对象的定义如下:

class pickle.Unpickler(file)

这需要从中它将读取一个泡菜数据流的文件类似对象。此类自动确定是否流数据以二进制模式编写与否,所以它并不需要酸洗厂标志。

文件必须有两种方法,需要一个 integer 参数, read ()方法和不需要参数的readline ()方法。这两种方法应返回一个字符串。因此文件可以开放供阅读、 一个StringIO对象或满足此接口的任何其他自定义对象的文件对象。

Unpickler对象具有一个 (或两个) 的公共方法:

load()

读取腌渍的对象表示形式从打开的 file 对象给出了在构造函数中,并返回所指明的重组的对象层次结构。

此方法自动确定是否流数据以二进制模式编写或不。

noload()

这就像load ()只是它不会实际创建的任何对象。这是主要用于查找泡菜数据流中所谓的"持久性 id",可能会被引用。请参阅更多的细节部分pickle 协议如下。

注: noload()方法只是当前创建的cPickle模块的Unpickler对象上可用。泡菜模块Unpicklers 没有noload()方法。

11.1.4. 哪些东西可以被 pickle 并且 unpickle?

可以 pickle 以下类型:

  • None, True, and False
  • integers, long integers, floating point numbers, complex numbers
  • normal and Unicode strings
  • tuples, lists, sets, and dictionaries containing only picklable objects
  • functions defined at the top level of a module
  • built-in functions defined at the top level of a module
  • classes that are defined at the top level of a module
  • instances of such classes whose __dict__ or the result of calling __getstate__() is picklable (see section The pickle protocol for details).

尝试序列化或者反序列化对象将会引发PicklingError异常 ;当发生这种情况,不明确的字节数可能已写入到基础文件。尝试序列化高度递归数据结构可能会超过最大递归深度, RuntimeError将会在这种情况下raise。你可以仔细地提高此限制与sys.setrecursionlimit()

请注意函数 (内置和用户定义) 腌渍就是由"完全限定"名称引用,不是按值。这意味着只有函数名称腌制,以及该函数定义中的模块的名称。腌渍既不是该函数的代码,也不是任何其功能属性。因此必须在 unpickling 的环境中,可导入定义的模块和模块必须包含已命名的对象,否则将引发异常。[] 4

同样,类腌渍的命名引用,所以在 unpickling 环境中的限制同样适用了。请注意没有任何的类的代码或数据腌制,以便在下面的示例类属性attr不还原在 unpickling 环境中:

class Foo:
    attr = 'a class attr'

picklestring = pickle.dumps(Foo)

这些限制是为什么必须在模块的顶层定义 picklable 函数和类。

同样地,当腌渍类的实例就是,他们班的代码和数据不腌渍就是和他们一起。腌渍就是唯一的实例数据。这是故意的所以你可以在类修复 bug 或向类添加方法和还装载了使用早期版本创建的类的对象。如果你计划要长期存活的对象,将会看到一个类的多个版本,可能值得可以将版本号放置在对象中,以便适当的转换可以由类的__setstate__()方法。

11.1.5. Pickle 协议

本节介绍"酸洗议定书",它定义施暴/unpickler 与正序列化的对象之间的接口。本议定书为您进行定义、 自定义和控制如何序列化和反序列化对象提供一种标准方式。这一节中的说明不包括特定的自定义,您可以用来使 unpickling 的环境更安全一些来自不受信任的泡菜数据流 ;请参阅更多的细节部分子类化 Unpicklers

11.1.5.1. Pickling and unpickling normal class instances

object.__getinitargs__()

Unpickled 腌渍的类实例时,它的__init__()方法通常是调用。如果它是可取的在 unpickling 上调用__init__()方法,旧样式类可以定义方法__getinitargs__(),它应该返回元组包含的参数要传递给类构造函数 (例如__init__() )。 __Getinitargs__()是在泡菜时调用 ;它返回的元组被列入泡菜的实例。

object.__getnewargs__()

新样式类型可以提供用于协议 2 的__getnewargs__()方法。如果类型建立一些内部的不变量,当创建的实例,或者如果内存分配受传递给__new__()方法的类型 (因为它是为元组和字符串) 的值,需要实现此方法。使用创建一个新样式类 C的实例

obj = C.__new__(C, *args)

args哪里在原始对象 ; 调用__getnewargs__()的结果如果没有__getnewargs__(),假定一个空的元组。

object.__getstate__()

类可以进一步影响如何腌渍了它们的实例 ;如果类定义了方法__getstate__(),它被称为和返回的状态腌制作为实例,而不是实例的字典的内容的内容。如果没有__getstate__()方法,实例的__dict__是腌渍。

object.__setstate__(state)

根据 unpickling,如果类还定义方法__setstate__(),它称为 unpickled 状态。[5]如果没有__setstate__()方法,腌渍的状态必须是一本字典和其项目分配给新实例字典。如果类定义了__getstate__()__setstate__(),状态对象不必一本字典,这些方法可以做他们想要什么。[] 6

新样式类es 如果__getstate__()返回 false 值, __setstate__()将不会调用方法。

在 unpickling 的时候,如__getattr__() __getattribute__()__setattr__()的一些方法可能要求该实例。这些方法依赖于一些内部的不变的情况下不真实,该类型应实现或__getinitargs__()__getnewargs__() ,建立这样一个不变量 ;否则,将调用__new__()__init__()都没有。

11.1.5.2. Pickling and unpickling extension types

object.__reduce__()

酸洗系统遇到的类型的对象时它什么都不知道 — — 如扩展类型 — — 它看起来在两个地方怎么去腌它,提示。一种替代方法是要实现一个__reduce__()方法的对象。如果提供,在酸洗时间__reduce__()将调用不带任何参数,它必须返回一个字符串或者一个元组。

如果返回一个字符串,它的名称腌渍就其内容是正常的全局变量。__reduce__()返回的字符串应该是该对象的本地名称相对于其模块 ;泡菜模块搜索模块命名空间,以确定该对象的模块。

当返回一个元组,则它必须长时间的两个和五个元素之间。也可以省略可选元素,或没有可供他们的价值。此元组的内容腌渍就是正常,用来构造对象 unpickling 次。每个元素的语义如下:

  • 一个可调用的对象,将调用以创建该对象的初始版本。该元组的下一个元素将提供此可赎回的和后来的元素的参数提供随后将用于完全重建腌渍的数据的其他状态信息。

    在 unpickling 环境中此对象必须是两个类别,可调用注册为"安全的构造函数"(见下文),或者它必须具有与真值的属性__safe_for_unpickling__ 否则,将在 unpickling 环境中引发的UnpicklingError 请注意,像往常一样,可调用本身腌制的名字。

  • 一个元组的参数的可调用的对象。

    2.5 版本中的更改:以前,这一论点也可能是没有

  • (可选),该对象的状态,它将被传递到该对象的__setstate__()方法中酸洗和 unpickling 正常类实例一节所述。如果对象有没有__setstate__()的方法,然后,上面的值必须是一本字典,它将被添加到该对象的__dict__

  • (可选) 一个迭代器 (和不是一个序列) 收益率连续列出的项目。这些列表项将腌渍,并追加到对象使用obj.append(item)obj.extend(list_of_items)这主要用于列表的子类,但是,只要他们有append ()extend()的方法,使用适当的签名可能由其他类使用。(是否使用append ()extend()取决于哪个泡菜使用协议版本的项目数以及要追加,因此都必须支持。

  • (可选) 一个迭代器 (不是一个序列) 产生连续的字典项,应该是元组形式的(键, 值)这些项目将腌渍,并存储到使用obj 【 关键词 】 = 的对象。这主要用于字典子类,但只要他们执行__setitem__(),可能由其他类使用。

object.__reduce_ex__(protocol)

有时是有用的在执行__reduce__()时知道的协议版本。这可以通过执行一个名为__reduce_ex__() ,而不是__reduce__()方法。 __reduce_ex__(),它存在的时候被称为在首选项中,在__reduce__() (你可能仍然提供__reduce__()为向后兼容性)。用单个整数参数,协议版本,将调用__reduce_ex__()方法。

对象类实现了__reduce__()__reduce_ex__()然而,如果一个子类重写__reduce__()但不是__reduce_ex__() __reduce_ex__()执行将检测到此,调用__reduce__()

替代对象来腌制上, 执行__reduce__()方法是使用copy_reg模块注册可调用。此模块提供程序注册"减少职能"的方法和构造函数用于用户定义的类型。减少功能作为上文所述的__reduce__()方法有着相同的语义学和界面,除了用一个单一的参数,要将腌渍的对象调用它们时。

注册建造师被认为是"安全的构造函数"unpickling 如上文所述的目的。

11.1.5.3. Pickling and unpickling external objects

为对象持久化泡菜模块支持的概念对外面的腌的数据码流对象的引用。此类对象引用的"持久性的 id",是只可打印 ASCII 字符的任意字符串。这种名称的解析未定义的泡菜模块 ;它将委托这项决议对酸洗和 unpickler 的用户定义函数。[] 7

若要定义外部持久性 id 解析,您需要设置persistent_id属性的施暴对象和 unpickler 对象的persistent_load属性。

要泡菜有外部的持久性 id 的对象,酸洗系统必须有一种自定义persistent_id()方法将对象作为参数并返回为或该对象的持久性 id。没有返回时,施暴只是泡菜对象作为正常。时返回了一个持久性 id 字符串,施暴将咸菜那根线,一直加上识别标志以便 unpickler 将作为一个持久性的 id 识别该字符串。

若要 unpickle 外部对象,unpickler 必须具有一个自定义的persistent_load()函数,采用一个持久性 id 字符串,并返回引用的对象。

这是一个愚蠢的例子,那可能会揭示更多:

import pickle
from cStringIO import StringIO

src = StringIO()
p = pickle.Pickler(src)

def persistent_id(obj):
    if hasattr(obj, 'x'):
        return 'the value %d' % obj.x
    else:
        return None

p.persistent_id = persistent_id

class Integer:
    def __init__(self, x):
        self.x = x
    def __str__(self):
        return 'My name is integer %d' % self.x

i = Integer(7)
print i
p.dump(i)

datastream = src.getvalue()
print repr(datastream)
dst = StringIO(datastream)

up = pickle.Unpickler(dst)

class FancyInteger(Integer):
    def __str__(self):
        return 'I am the integer %d' % self.x

def persistent_load(persid):
    if persid.startswith('the value '):
        value = int(persid.split()[2])
        return FancyInteger(value)
    else:
        raise pickle.UnpicklingError, 'Invalid persistent id'

up.persistent_load = persistent_load

j = up.load()
print j

cPickle模块中,unpickler 的persistent_load属性也可以在这种情况下对一个 Python 列表,设置,当 unpickler 只是达到一个持久性的 id,将持久性 id 字符串追加到此列表中。此功能的存在,所以泡菜数据流可以"不容忽视"的对象引用没有实际实例化泡菜中的所有对象。[8]设置persistent_load到列表是通常与结合使用 Unpickler 的noload()方法。

11.1.6. Subclassing Unpicklers

默认情况下,unpickling 将导入在泡菜数据中找到的任何类。您可以控制到底什么获取 unpickled 和所谓的获取通过自定义您的 unpickler。不幸的是,你究竟怎么做这取决于您使用的腌菜或是cPickle有别。[] 9

泡菜模块中,您需要从Unpickler,重写load_global()方法中派生出子类。 load_global()从泡菜的数据流在哪里的第一行会包含类的模块的名称,第二行将该实例的类的名称改为两行。然后,它查找类、 可能导入模块和挖出的属性,然后它将追加它发现到 unpickler 的堆栈。晚些时候开始,此类将分配到一个空的类,作为一种方式的神奇地创建一个实例,而无需调用其类__init__()__class__属性。你的工作 (如果您选择接受它),将会有load_global()推到 unpickler 上的堆栈,您认为安全的 unpickle 任何类的一个已知的安全版本。它是由你来产生的一类。或者你可能会引发错误,如果你想要禁止所有 unpickling 的实例。如果这听起来像一个 hack,你是对的。请参阅源代码,使这项工作。

事情是少许清洁剂cPickle,但不是很多。若要控制什么获取 unpickled,可以将 unpickler 的find_global属性设置为一个函数或没有如果这是然后 unpickle 实例的任何企图将引发的UnpicklingError如果它是一个函数,然后它应该接受模块名称和类的名称,并返回相应的类对象。它负责查找类并执行任何必要的进口,以及它可能会产生一个错误以防止类的实例被高。

这个故事的寓意是你应该确实要仔细考虑您的应用程序 unpickles 的字符串的源。

11.1.7. 例子

对于最简单的代码,使用dump()load ()函数。请注意自引用的列表是腌渍,并且正确还原。

import pickle

data1 = {'a': [1, 2.0, 3, 4+6j],
         'b': ('string', u'Unicode string'),
         'c': None}

selfref_list = [1, 2, 3]
selfref_list.append(selfref_list)

output = open('data.pkl', 'wb')

# Pickle dictionary using protocol 0.
pickle.dump(data1, output)

# Pickle the list using the highest protocol available.
pickle.dump(selfref_list, output, -1)

output.close()

下面的示例读取结果腌的数据。当读取泡菜包含的文件,应以二进制模式打开的文件,因为您不能确定是否使用 ASCII 或二进制格式。

import pprint, pickle

pkl_file = open('data.pkl', 'rb')

data1 = pickle.load(pkl_file)
pprint.pprint(data1)

data2 = pickle.load(pkl_file)
pprint.pprint(data2)

pkl_file.close()

这里是一个更大的示例,演示如何修改一类酸洗行为。输送类打开一个文本文件中,并返回的行号和行的内容每次调用它的readline ()方法。如果一个输送实例腌制,所有属性除了文件对象成员都保存。Unpickled 的实例时,重新打开该文件,并阅读恢复从最后一个位置。 __Setstate__()__getstate__()方法用于实现此行为。

#!/usr/local/bin/python

class TextReader:
    """Print and number lines in a text file."""
    def __init__(self, file):
        self.file = file
        self.fh = open(file)
        self.lineno = 0

    def readline(self):
        self.lineno = self.lineno + 1
        line = self.fh.readline()
        if not line:
            return None
        if line.endswith("\n"):
            line = line[:-1]
        return "%d: %s" % (self.lineno, line)

    def __getstate__(self):
        odict = self.__dict__.copy() # copy the dict since we change it
        del odict['fh']              # remove filehandle entry
        return odict

    def __setstate__(self, dict):
        fh = open(dict['file'])      # reopen file
        count = dict['lineno']       # read from file...
        while count:                 # until line count is restored
            fh.readline()
            count = count - 1
        self.__dict__.update(dict)   # update attributes
        self.fh = fh                 # save the file object

示例用法可能像这样:

>>> import TextReader
>>> obj = TextReader.TextReader("TextReader.py")
>>> obj.readline()
'1: #!/usr/local/bin/python'
>>> obj.readline()
'2: '
>>> obj.readline()
'3: class TextReader:'
>>> import pickle
>>> pickle.dump(obj, open('save.p', 'wb'))

如果你想要看到,pickle如何通过 Python 进程工作的,执行下一步之前启动另一个 Python 的会话。What follows can happen from either the same process or a new process.

>>> import pickle
>>> reader = pickle.load(open('save.p', 'rb'))
>>> reader.readline()
'4:     """Print and number lines in a text file."""'

请参见

Module copy_reg
Pickle interface constructor registration for extension types.
Module shelve
Indexed databases of objects; uses pickle.
Module copy
Shallow and deep object copying.
Module marshal
High-performance serialization of built-in types.

11.2. cPickle一个更快的 pickle

CPickle模块支持序列化和反序列化的 Python 对象,提供一个接口和一个几乎相同的泡菜模块的功能。有几个差异,最重要的性能和 subclassability。

首先, cPickle可以比pickle快 1000倍因为前者实行 c第二,callables Pickler()Unpickler()cPickle模块而不是类的功能。这意味着您不能使用它们来派生自定义酸洗和 unpickling 的子类。大多数应用程序不需要此功能,并应得益于cPickle模块大大提高性能。

CPickle是相同的所以它是可能与现有的 pickle 交替使用泡菜cPickle和泡菜数据流产生的泡菜[] 10

有额外 API 中cPicklepickle,之间的细微差别,然而对于大多数应用程序,他们是可以互换的。泡菜模块文档中,包括一个列表记录的差异提供了更多的文档。

脚注

[1]Don’t confuse this with the marshal module
[2]In the pickle module these callables are classes, which you could subclass to customize the behavior. However, in the cPickle module these callables are factory functions and so cannot be subclassed. One common reason to subclass is to control what objects can actually be unpickled. See section Subclassing Unpicklers for more details.
[3]Warning: this is intended for pickling multiple objects without intervening modifications to the objects or their parts. If you modify an object and then pickle it again using the same Pickler instance, the object is not pickled again — a reference to it is pickled and the Unpickler will return the old value, not the modified one. There are two problems here: (1) detecting changes, and (2) marshalling a minimal set of changes. Garbage Collection may also become a problem here.
[4]The exception raised will likely be an ImportError or an AttributeError but it could be something else.
[5]These methods can also be used to implement copying class instances.
[6]This protocol is also used by the shallow and deep copying operations defined in the copy module.
[7]The actual mechanism for associating these user defined functions is slightly different for pickle and cPickle. The description given here works the same for both implementations. Users of the pickle module could also use subclassing to effect the same results, overriding the persistent_id() and persistent_load() methods in the derived classes.
[8]We’ll leave you with the image of Guido and Jim sitting around sniffing pickles in their living rooms.
[9]A word of caution: the mechanisms described here use internal attributes and methods, which are subject to change in future versions of Python. We intend to someday provide a common interface for controlling this behavior, which will work in either pickle or cPickle.
[10]Since the pickle data format is actually a tiny stack-oriented programming language, and some freedom is taken in the encodings of certain objects, it is possible that the two modules produce different data streams for the same input objects. However it is guaranteed that they will always be able to read each other’s data streams.