“Python/docs/3.9/library/pickle”的版本间差异

来自菜鸟教程
Python/docs/3.9/library/pickle
跳转至:导航、​搜索
(autoload)
 
(Page commit)
 
第1行: 第1行:
 +
{{DISPLAYTITLE:pickle — Python 对象序列化 — Python 文档}}
 
<div id="module-pickle" class="section">
 
<div id="module-pickle" class="section">
  
 
<span id="pickle-python-object-serialization"></span>
 
<span id="pickle-python-object-serialization"></span>
= [[#module-pickle|<code>pickle</code>]] --- Python object serialization =
+
= pickle Python 对象序列化 =
  
'''Source code:''' [https://github.com/python/cpython/tree/3.9/Lib/pickle.py Lib/pickle.py]
+
'''源代码:''' [[#id1|<span id="id2" class="problematic">:source:`Lib/pickle.py`</span>]]
  
The [[#module-pickle|<code>pickle</code>]] module implements binary protocols for serializing and
+
 
de-serializing a Python object structure. ''&quot;Pickling&quot;'' is the process
+
-----
whereby a Python object hierarchy is converted into a byte stream, and
+
 
''&quot;unpickling&quot;'' is the inverse operation, whereby a byte stream
+
[[#module-pickle|pickle]] 模块实现了用于序列化和反序列化 Python 对象结构的二进制协议。 ''“Pickling”'' 是将 Python 对象层次结构转换为字节流的过程,而 ''“unpickling”'' 是逆操作,由此字节流(来自 [[../../glossary#term-binary-file|二进制file]] [[../../glossary#term-bytes-like-object|bytes-like object]]) 被转换回对象层次结构。 酸洗(和取消酸洗)也称为“序列化”、“编组”、[[#id9|1]] 或“扁平化”; 然而,为了避免混淆,这里使用的术语是“酸洗”和“解酸”。
(from a [[../../glossary#term-binary-file|<span class="xref std std-term">binary file</span>]] or [[../../glossary#term-bytes-like-object|<span class="xref std std-term">bytes-like object</span>]]) is converted
 
back into an object hierarchy. Pickling (and unpickling) is alternatively
 
known as &quot;serialization&quot;, &quot;marshalling,&quot; [[#id7|1]] or &quot;flattening&quot;; however, to
 
avoid confusion, the terms used here are &quot;pickling&quot; and &quot;unpickling&quot;.
 
  
 
<div class="admonition warning">
 
<div class="admonition warning">
第19行: 第16行:
 
警告
 
警告
  
The <code>pickle</code> module '''is not secure'''. Only unpickle data you trust.
+
<code>pickle</code> 模块 '''不安全''' 。 只解压您信任的数据。
  
It is possible to construct malicious pickle data which will '''execute
+
有可能构建恶意pickle数据,在unpickling'''期间'''执行任意代码。 永远不要解开可能来自不受信任的来源或可能被篡改的数据。
arbitrary code during unpickling'''. Never unpickle data that could have come
 
from an untrusted source, or that could have been tampered with.
 
  
Consider signing data with [[../hmac#module-hmac|<code>hmac</code>]] if you need to ensure that it has not
+
如果您需要确保数据未被篡改,请考虑使用 [[../hmac#module-hmac|hmac]] 对数据进行签名。
been tampered with.
 
  
Safer serialization formats such as [[../json#module-json|<code>json</code>]] may be more appropriate if
+
如果您正在处理不受信任的数据,更安全的序列化格式(例如 [[../json#module-json|json]])可能更合适。 参见 [[#comparison-with-json|json]] 的比较。
you are processing untrusted data. See [[#comparison-with-json|<span class="std std-ref">Comparison with json</span>]].
 
  
  
第35行: 第28行:
 
<div id="relationship-to-other-python-modules" class="section">
 
<div id="relationship-to-other-python-modules" class="section">
  
== Relationship to other Python modules ==
+
== 与其他 Python 模块的关系 ==
  
 
<div id="comparison-with-marshal" class="section">
 
<div id="comparison-with-marshal" class="section">
  
=== Comparison with <code>marshal</code> ===
+
=== 与marshal的比较 ===
  
Python has a more primitive serialization module called [[../marshal#module-marshal|<code>marshal</code>]], but in
+
Python 有一个更原始的序列化模块,称为 [[../marshal#module-marshal|marshal]],但总的来说,[[#module-pickle|pickle]] 应该始终是序列化 Python 对象的首选方式。 [[../marshal#module-marshal|marshal]] 的存在主要是为了支持 Python <code>.pyc</code> 文件。
general [[#module-pickle|<code>pickle</code>]] should always be the preferred way to serialize Python
 
objects. [[../marshal#module-marshal|<code>marshal</code>]] exists primarily to support Python's <code>.pyc</code>
 
files.
 
  
The [[#module-pickle|<code>pickle</code>]] module differs from [[../marshal#module-marshal|<code>marshal</code>]] in several significant ways:
+
[[#module-pickle|pickle]] 模块在几个重要方面与 [[../marshal#module-marshal|marshal]] 不同:
  
 
<ul>
 
<ul>
<li><p>The [[#module-pickle|<code>pickle</code>]] module keeps track of the objects it has already serialized,
+
<li><p>[[#module-pickle|pickle]] 模块跟踪它已经序列化的对象,以便以后对同一对象的引用不会再次序列化。 [[../marshal#module-marshal|marshal]] 不这样做。</p>
so that later references to the same object won't be serialized again.
+
<p>这对递归对象和对象共享都有影响。 递归对象是包含对自身的引用的对象。 这些不是由 marshal 处理的,实际上,尝试 marshal 递归对象会使您的 Python 解释器崩溃。 当在被序列化的对象层次结构中的不同位置对同一对象有多个引用时,就会发生对象共享。 [[#module-pickle|pickle]] 仅存储此类对象一次,并确保所有其他引用都指向主副本。 共享对象保持共享状态,这对于可变对象非常重要。</p></li>
[[../marshal#module-marshal|<code>marshal</code>]] doesn't do this.</p>
+
<li><p>[[../marshal#module-marshal|marshal]] 不能用于序列化用户定义的类及其实例。 [[#module-pickle|pickle]] 可以透明地保存和恢复类实例,但是类定义必须是可导入的,并且与存储对象时存在于同一模块中。</p></li>
<p>This has implications both for recursive objects and object sharing. Recursive
+
<li><p>[[../marshal#module-marshal|marshal]] 序列化格式不能保证跨 Python 版本可移植。 因为 Python 的主要工作是支持 <code>.pyc</code> 文件,所以 Python 实现者保留在需要时以非向后兼容的方式更改序列化格式的权利。 [[#module-pickle|pickle]] 序列化格式保证在 Python 版本之间向后兼容,前提是选择了兼容的 pickle 协议,并且如果您的数据跨越了那个独特的突破性更改语言,pickle 和 unpickling 代码处理 Python 2 Python 3 的类型差异边界。</p></li></ul>
objects are objects that contain references to themselves. These are not
 
handled by marshal, and in fact, attempting to marshal recursive objects will
 
crash your Python interpreter. Object sharing happens when there are multiple
 
references to the same object in different places in the object hierarchy being
 
serialized. [[#module-pickle|<code>pickle</code>]] stores such objects only once, and ensures that all
 
other references point to the master copy. Shared objects remain shared, which
 
can be very important for mutable objects.</p></li>
 
<li><p>[[../marshal#module-marshal|<code>marshal</code>]] cannot be used to serialize user-defined classes and their
 
instances. [[#module-pickle|<code>pickle</code>]] can save and restore class instances transparently,
 
however the class definition must be importable and live in the same module as
 
when the object was stored.</p></li>
 
<li><p>The [[../marshal#module-marshal|<code>marshal</code>]] serialization format is not guaranteed to be portable
 
across Python versions. Because its primary job in life is to support
 
<code>.pyc</code> files, the Python implementers reserve the right to change the
 
serialization format in non-backwards compatible ways should the need arise.
 
The [[#module-pickle|<code>pickle</code>]] serialization format is guaranteed to be backwards compatible
 
across Python releases provided a compatible pickle protocol is chosen and
 
pickling and unpickling code deals with Python 2 to Python 3 type differences
 
if your data is crossing that unique breaking change language boundary.</p></li></ul>
 
  
  
第77行: 第48行:
 
<div id="comparison-with-json" class="section">
 
<div id="comparison-with-json" class="section">
  
<span id="id2"></span>
+
<span id="id4"></span>
=== Comparison with <code>json</code> ===
+
=== 与json的比较 ===
  
There are fundamental differences between the pickle protocols and
+
pickle 协议和 [http://json.org JSON(JavaScript Object Notation)] 之间存在根本区别:
[http://json.org JSON (JavaScript Object Notation)]:
 
  
* JSON is a text serialization format (it outputs unicode text, although most of the time it is then encoded to <code>utf-8</code>), while pickle is a binary serialization format;
+
* JSON 是一种文本序列化格式(它输出 unicode 文本,尽管大多数时候它会被编码为 <code>utf-8</code>),而 pickle 是一种二进制序列化格式;
* JSON is human-readable, while pickle is not;
+
* JSON 是人类可读的,而 pickle 不是;
* JSON is interoperable and widely used outside of the Python ecosystem, while pickle is Python-specific;
+
* JSON 是可互操作的,并且在 Python 生态系统之外广泛使用,而 pickle 是特定于 Python 的;
* JSON, by default, can only represent a subset of the Python built-in types, and no custom classes; pickle can represent an extremely large number of Python types (many of them automatically, by clever usage of Python's introspection facilities; complex cases can be tackled by implementing [[#pickle-inst|<span class="std std-ref">specific object APIs</span>]]);
+
* 默认情况下,JSON 只能表示 Python 内置类型的一个子集,而没有自定义类; pickle 可以表示非常多的 Python 类型(其中许多是自动的,通过巧妙地使用 Python 的自省设施;复杂的情况可以通过实现 [[#pickle-inst|特定对象 API]] 来解决);
* Unlike pickle, deserializing untrusted JSON does not in itself create an arbitrary code execution vulnerability.
+
* pickle 不同,反序列化不受信任的 JSON 本身不会产生任意代码执行漏洞。
  
 
<div class="admonition seealso">
 
<div class="admonition seealso">
  
参见
+
也可以看看
  
The [[../json#module-json|<code>json</code>]] module: a standard library module allowing JSON
+
[[../json#module-json|json]] 模块:一个允许 JSON 序列化和反序列化的标准库模块。
serialization and deserialization.
 
  
  
第105行: 第74行:
  
 
<span id="pickle-protocols"></span>
 
<span id="pickle-protocols"></span>
== Data stream format ==
+
== 数据流格式 ==
  
The data format used by [[#module-pickle|<code>pickle</code>]] is Python-specific. This has the
+
[[#module-pickle|pickle]] 使用的数据格式是 Python 特定的。 这样做的好处是不受外部标准的限制,例如 JSON 或 XDR(不能代表指针共享); 然而,这意味着非 Python 程序可能无法重建腌制的 Python 对象。
advantage that there are no restrictions imposed by external standards such as
 
JSON or XDR (which can't represent pointer sharing); however it means that
 
non-Python programs may not be able to reconstruct pickled Python objects.
 
  
By default, the [[#module-pickle|<code>pickle</code>]] data format uses a relatively compact binary
+
默认情况下,[[#module-pickle|pickle]] 数据格式使用相对紧凑的二进制表示。 如果您需要最佳尺寸特征,您可以有效地 [[../archiving|压缩]] 腌制数据。
representation. If you need optimal size characteristics, you can efficiently
 
[[../archiving|<span class="doc">compress</span>]] pickled data.
 
  
The module [[../pickletools#module-pickletools|<code>pickletools</code>]] contains tools for analyzing data streams
+
模块 [[../pickletools#module-pickletools|pickletools]] 包含用于分析由 [[#module-pickle|pickle]] 生成的数据流的工具。 [[../pickletools#module-pickletools|pickletools]] 源代码对pickle 协议使用的操作码有大量注释。
generated by [[#module-pickle|<code>pickle</code>]]. [[../pickletools#module-pickletools|<code>pickletools</code>]] source code has extensive
 
comments about opcodes used by pickle protocols.
 
  
There are currently 6 different protocols which can be used for pickling.
+
目前有 6 种不同的协议可用于酸洗。 使用的协议越高,读取生成的泡菜所需的 Python 版本就越新。
The higher the protocol used, the more recent the version of Python needed
 
to read the pickle produced.
 
  
* Protocol version 0 is the original &quot;human-readable&quot; protocol and is backwards compatible with earlier versions of Python.
+
* 协议版本 0 是原始的“人类可读”协议,向后兼容早期版本的 Python。
* Protocol version 1 is an old binary format which is also compatible with earlier versions of Python.
+
* 协议版本 1 是一种旧的二进制格式,它也与早期版本的 Python 兼容。
* Protocol version 2 was introduced in Python 2.3. It provides much more efficient pickling of [[../../glossary#term-new-style-class|<span class="xref std std-term">new-style class</span>]]es. Refer to <span id="index-2" class="target"></span>[https://www.python.org/dev/peps/pep-0307 '''PEP 307'''] for information about improvements brought by protocol 2.
+
* 协议版本 2 是在 Python 2.3 中引入的。 它为 [[../../glossary#term-new-style-class|新式类]] 提供了更有效的酸洗。 有关协议 2 带来的改进的信息,请参阅 <span id="index-2" class="target"></span>[https://www.python.org/dev/peps/pep-0307 PEP 307]
* Protocol version 3 was added in Python 3.0. It has explicit support for [[../stdtypes#bytes|<code>bytes</code>]] objects and cannot be unpickled by Python 2.x. This was the default protocol in Python 3.0--3.7.
+
* Python 3.0 中添加了协议版本 3。 它明确支持 [[../stdtypes#bytes|bytes]] 对象,并且不能被 Python 2.x 解压。 这是 Python 3.0-3.7 中的默认协议。
* Protocol version 4 was added in Python 3.4. It adds support for very large objects, pickling more kinds of objects, and some data format optimizations. It is the default protocol starting with Python 3.8. Refer to <span id="index-3" class="target"></span>[https://www.python.org/dev/peps/pep-3154 '''PEP 3154'''] for information about improvements brought by protocol 4.
+
* Python 3.4 中添加了协议版本 4。 它增加了对超大对象的支持,酸洗更多种类的对象,以及一些数据格式优化。 它是从 Python 3.8 开始的默认协议。 有关协议 4 带来的改进的信息,请参阅 <span id="index-3" class="target"></span>[https://www.python.org/dev/peps/pep-3154 PEP 3154]
* Protocol version 5 was added in Python 3.8. It adds support for out-of-band data and speedup for in-band data. Refer to <span id="index-4" class="target"></span>[https://www.python.org/dev/peps/pep-0574 '''PEP 574'''] for information about improvements brought by protocol 5.
+
* Python 3.8 中添加了协议版本 5。 它增加了对带外数据的支持和对带内数据的加速。 有关协议 5 带来的改进的信息,请参阅 <span id="index-4" class="target"></span>[https://www.python.org/dev/peps/pep-0574 PEP 574]
  
 
<div class="admonition note">
 
<div class="admonition note">
  
注解
+
笔记
  
Serialization is a more primitive notion than persistence; although
+
序列化是一个比持久化更原始的概念; [[#module-pickle|pickle]]虽然读写文件对象,但它没有处理命名持久对象的问题,也没有处理持久对象的并发访问(甚至更复杂)的问题。 [[#module-pickle|pickle]] 模块可以将复杂对象转换为字节流,也可以将字节流转换为具有相同内部结构的对象。 也许对这些字节流做的最明显的事情是将它们写入文件,但也可以通过网络发送它们或将它们存储在数据库中。 [[../shelve#module-shelve|shelve]] 模块提供了一个简单的接口来pickle 和unpickle DBM 样式数据库文件上的对象。
[[#module-pickle|<code>pickle</code>]] reads and writes file objects, it does not handle the issue of
 
naming persistent objects, nor the (even more complicated) issue of concurrent
 
access to persistent objects. The [[#module-pickle|<code>pickle</code>]] module can transform a complex
 
object into a byte stream and it can transform the byte stream into an object
 
with the same internal structure. Perhaps the most obvious thing to do with
 
these byte streams is to write them onto a file, but it is also conceivable to
 
send them across a network or store them in a database. The [[../shelve#module-shelve|<code>shelve</code>]]
 
module provides a simple interface to pickle and unpickle objects on
 
DBM-style database files.
 
  
  
第152行: 第103行:
 
<div id="module-interface" class="section">
 
<div id="module-interface" class="section">
  
== Module Interface ==
+
== 模块接口 ==
  
To serialize an object hierarchy, you simply call the [[#pickle.dumps|<code>dumps()</code>]] function.
+
要序列化对象层次结构,只需调用 [[#pickle.dumps|dumps()]] 函数。 类似地,要反序列化数据流,您可以调用 [[#pickle.loads|loads()]] 函数。 但是,如果您想对序列化和反序列化进行更多控制,则可以分别创建 [[#pickle.Pickler|Pickler]] [[#pickle.Unpickler|Unpickler]] 对象。
Similarly, to de-serialize a data stream, you call the [[#pickle.loads|<code>loads()</code>]] function.
 
However, if you want more control over serialization and de-serialization,
 
you can create a [[#pickle.Pickler|<code>Pickler</code>]] or an [[#pickle.Unpickler|<code>Unpickler</code>]] object, respectively.
 
  
The [[#module-pickle|<code>pickle</code>]] module provides the following constants:
+
[[#module-pickle|pickle]] 模块提供以下常量:
  
; <code>pickle.</code><code>HIGHEST_PROTOCOL</code>
+
; <span class="sig-prename descclassname"><span class="pre">pickle.</span></span><span class="sig-name descname"><span class="pre">HIGHEST_PROTOCOL</span></span>
: An integer, the highest [[#pickle-protocols|<span class="std std-ref">protocol version</span>]] available. This value can be passed as a ''protocol'' value to functions [[#pickle.dump|<code>dump()</code>]] and [[#pickle.dumps|<code>dumps()</code>]] as well as the [[#pickle.Pickler|<code>Pickler</code>]] constructor.
+
: 一个整数,可用的最高 [[#pickle-protocols|协议版本]] 。 该值可以作为 ''protocol'' 值传递给函数 [[#pickle.dump|dump()]] [[#pickle.dumps|dumps()]] 以及 [[#pickle.Pickler|Picker]] 构造函数。
  
 
<dl>
 
<dl>
<dt><code>pickle.</code><code>DEFAULT_PROTOCOL</code></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">pickle.</span></span><span class="sig-name descname"><span class="pre">DEFAULT_PROTOCOL</span></span></dt>
<dd><p>An integer, the default [[#pickle-protocols|<span class="std std-ref">protocol version</span>]] used
+
<dd><p>一个整数,默认 [[#pickle-protocols|协议版本]] 用于酸洗。 可能小于 [[#pickle.HIGHEST_PROTOCOL|HIGHEST_PROTOCOL]]。 目前默认的协议是 4,最初是在 Python 3.4 中引入的,与之前的版本不兼容。</p>
for pickling. May be less than [[#pickle.HIGHEST_PROTOCOL|<code>HIGHEST_PROTOCOL</code>]]. Currently the
 
default protocol is 4, first introduced in Python 3.4 and incompatible
 
with previous versions.</p>
 
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">3.0 版更改: </span>The default protocol is 3.</p>
+
<p><span class="versionmodified changed">3.0版本变化:</span>默认协议为3。</p>
  
 
</div>
 
</div>
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">3.8 版更改: </span>The default protocol is 4.</p>
+
<p><span class="versionmodified changed">3.8版本变化:</span>默认协议为4。</p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
The [[#module-pickle|<code>pickle</code>]] module provides the following functions to make the pickling
+
[[#module-pickle|pickle]]模块提供了以下功能,让pickle过程更加方便:
process more convenient:
 
  
 
<dl>
 
<dl>
<dt><code>pickle.</code><code>dump</code><span class="sig-paren">(</span>''obj'', ''file'', ''protocol=None'', ''\*'', ''fix_imports=True'', ''buffer_callback=None''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">pickle.</span></span><span class="sig-name descname"><span class="pre">dump</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">obj</span></span>'', ''<span class="n"><span class="pre">file</span></span>'', ''<span class="n"><span class="pre">protocol</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="o"><span class="pre">*</span></span>'', ''<span class="n"><span class="pre">fix_imports</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span>'', ''<span class="n"><span class="pre">buffer_callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Write the pickled representation of the object ''obj'' to the open
+
<dd><p>将对象 ''obj'' 的腌制表示写入打开的 [[../../glossary#term-file-object|文件对象]] ''文件'' 。 这相当于 <code>Pickler(file, protocol).dump(obj)</code></p>
[[../../glossary#term-file-object|<span class="xref std std-term">file object</span>]] ''file''. This is equivalent to
+
<p>参数 ''file''''protocol''''fix_imports'' ''buffer_callback'' [[#pickle.Pickler|Pickler]] 构造函数中的含义相同。</p>
<code>Pickler(file, protocol).dump(obj)</code>.</p>
 
<p>Arguments ''file'', ''protocol'', ''fix_imports'' and ''buffer_callback'' have
 
the same meaning as in the [[#pickle.Pickler|<code>Pickler</code>]] constructor.</p>
 
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">3.8 版更改: </span>The ''buffer_callback'' argument was added.</p>
+
<p><span class="versionmodified changed"> 3.8 版更改: </span> 添加了 ''buffer_callback'' 参数。</p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
 
<dl>
 
<dl>
<dt><code>pickle.</code><code>dumps</code><span class="sig-paren">(</span>''obj'', ''protocol=None'', ''\*'', ''fix_imports=True'', ''buffer_callback=None''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">pickle.</span></span><span class="sig-name descname"><span class="pre">dumps</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">obj</span></span>'', ''<span class="n"><span class="pre">protocol</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="o"><span class="pre">*</span></span>'', ''<span class="n"><span class="pre">fix_imports</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span>'', ''<span class="n"><span class="pre">buffer_callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Return the pickled representation of the object ''obj'' as a [[../stdtypes#bytes|<code>bytes</code>]] object,
+
<dd><p>将对象 ''obj'' 的腌制表示返回为 [[../stdtypes#bytes|bytes]] 对象,而不是将其写入文件。</p>
instead of writing it to a file.</p>
+
<p>参数 ''protocol''''fix_imports'' ''buffer_callback'' [[#pickle.Pickler|Picker]] 构造函数中的含义相同。</p>
<p>Arguments ''protocol'', ''fix_imports'' and ''buffer_callback'' have the same
 
meaning as in the [[#pickle.Pickler|<code>Pickler</code>]] constructor.</p>
 
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">3.8 版更改: </span>The ''buffer_callback'' argument was added.</p>
+
<p><span class="versionmodified changed"> 3.8 版更改: </span> 添加了 ''buffer_callback'' 参数。</p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
 
<dl>
 
<dl>
<dt><code>pickle.</code><code>load</code><span class="sig-paren">(</span>''file'', ''\*'', ''fix_imports=True'', ''encoding=&quot;ASCII&quot;'', ''errors=&quot;strict&quot;'', ''buffers=None''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">pickle.</span></span><span class="sig-name descname"><span class="pre">load</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">file</span></span>'', ''<span class="o"><span class="pre">*</span></span>'', ''<span class="n"><span class="pre">fix_imports</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span>'', ''<span class="n"><span class="pre">encoding</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'ASCII'</span></span>'', ''<span class="n"><span class="pre">errors</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'strict'</span></span>'', ''<span class="n"><span class="pre">buffers</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Read the pickled representation of an object from the open [[../../glossary#term-file-object|<span class="xref std std-term">file object</span>]]
+
<dd><p>从打开的 [[../../glossary#term-file-object|文件对象]] ''文件'' 中读取对象的酸洗表示,并返回其中指定的重组对象层次结构。 这相当于 <code>Unpickler(file).load()</code></p>
''file'' and return the reconstituted object hierarchy specified therein.
+
<p>pickle 的协议版本是自动检测的,因此不需要协议参数。 超过对象的pickle 表示的字节将被忽略。</p>
This is equivalent to <code>Unpickler(file).load()</code>.</p>
+
<p>参数 ''file''''fix_imports''''encoding''''errors''''strict'' ''buffers''[[#pickle.Unpickler|Unpickler]] 构造函数中的含义相同。</p>
<p>The protocol version of the pickle is detected automatically, so no
 
protocol argument is needed. Bytes past the pickled representation
 
of the object are ignored.</p>
 
<p>Arguments ''file'', ''fix_imports'', ''encoding'', ''errors'', ''strict'' and ''buffers''
 
have the same meaning as in the [[#pickle.Unpickler|<code>Unpickler</code>]] constructor.</p>
 
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">3.8 版更改: </span>The ''buffers'' argument was added.</p>
+
<p><span class="versionmodified changed"> 3.8 版更改: </span> 添加了 ''buffers'' 参数。</p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
 
<dl>
 
<dl>
<dt><code>pickle.</code><code>loads</code><span class="sig-paren">(</span>''data'', ''/'', ''\*'', ''fix_imports=True'', ''encoding=&quot;ASCII&quot;'', ''errors=&quot;strict&quot;'', ''buffers=None''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">pickle.</span></span><span class="sig-name descname"><span class="pre">loads</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">data</span></span>'', ''<span class="o"><span class="pre">/</span></span>'', ''<span class="o"><span class="pre">*</span></span>'', ''<span class="n"><span class="pre">fix_imports</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span>'', ''<span class="n"><span class="pre">encoding</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'ASCII'</span></span>'', ''<span class="n"><span class="pre">errors</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'strict'</span></span>'', ''<span class="n"><span class="pre">buffers</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Return the reconstituted object hierarchy of the pickled representation
+
<dd><p>返回对象的pickle 表示''data'' 的重构对象层次结构。 ''data'' 必须是一个 [[../../glossary#term-bytes-like-object|bytes-like object]]</p>
''data'' of an object. ''data'' must be a [[../../glossary#term-bytes-like-object|<span class="xref std std-term">bytes-like object</span>]].</p>
+
<p>pickle 的协议版本是自动检测的,因此不需要协议参数。 超过对象的pickle 表示的字节将被忽略。</p>
<p>The protocol version of the pickle is detected automatically, so no
+
<p>参数 ''file''''fix_imports''''encoding''''errors''''strict'' ''buffers''[[#pickle.Unpickler|Unpickler]] 构造函数中的含义相同。</p>
protocol argument is needed. Bytes past the pickled representation
 
of the object are ignored.</p>
 
<p>Arguments ''file'', ''fix_imports'', ''encoding'', ''errors'', ''strict'' and ''buffers''
 
have the same meaning as in the [[#pickle.Unpickler|<code>Unpickler</code>]] constructor.</p>
 
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">3.8 版更改: </span>The ''buffers'' argument was added.</p>
+
<p><span class="versionmodified changed"> 3.8 版更改: </span> 添加了 ''buffers'' 参数。</p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
The [[#module-pickle|<code>pickle</code>]] module defines three exceptions:
+
[[#module-pickle|pickle]] 模块定义了三个异常:
  
; ''exception'' <code>pickle.</code><code>PickleError</code>
+
; ''<span class="pre">exception</span>'' <span class="sig-prename descclassname"><span class="pre">pickle.</span></span><span class="sig-name descname"><span class="pre">PickleError</span></span>
: Common base class for the other pickling exceptions. It inherits [[../exceptions#Exception|<code>Exception</code>]].
+
: 其他酸洗异常的公共基类。 它继承了 [[../exceptions#Exception|异常]]
  
 
<dl>
 
<dl>
<dt>''exception'' <code>pickle.</code><code>PicklingError</code></dt>
+
<dt>''<span class="pre">exception</span>'' <span class="sig-prename descclassname"><span class="pre">pickle.</span></span><span class="sig-name descname"><span class="pre">PicklingError</span></span></dt>
<dd><p>Error raised when an unpicklable object is encountered by [[#pickle.Pickler|<code>Pickler</code>]].
+
<dd><p>[[#pickle.Pickler|Pickler]] 遇到不可拾取的对象时引发错误。 它继承了 [[#pickle.PickleError|PickleError]]</p>
It inherits [[#pickle.PickleError|<code>PickleError</code>]].</p>
+
<p>请参阅[[#pickle-picklable|可以腌制和不腌制的物品?]]了解可以腌制的物品种类。</p></dd></dl>
<p>Refer to [[#pickle-picklable|<span class="std std-ref">What can be pickled and unpickled?</span>]] to learn what kinds of objects can be
 
pickled.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt>''exception'' <code>pickle.</code><code>UnpicklingError</code></dt>
+
<dt>''<span class="pre">exception</span>'' <span class="sig-prename descclassname"><span class="pre">pickle.</span></span><span class="sig-name descname"><span class="pre">UnpicklingError</span></span></dt>
<dd><p>Error raised when there is a problem unpickling an object, such as a data
+
<dd><p>当解压对象出现问题时引发错误,例如数据损坏或安全违规。 它继承了 [[#pickle.PickleError|PickleError]]</p>
corruption or a security violation. It inherits [[#pickle.PickleError|<code>PickleError</code>]].</p>
+
<p>请注意,在 unpickling 期间也可能引发其他异常,包括(但不一定限于)AttributeError、EOFError、ImportError 和 IndexError。</p></dd></dl>
<p>Note that other exceptions may also be raised during unpickling, including
 
(but not necessarily limited to) AttributeError, EOFError, ImportError, and
 
IndexError.</p></dd></dl>
 
  
The [[#module-pickle|<code>pickle</code>]] module exports three classes, [[#pickle.Pickler|<code>Pickler</code>]],
+
[[#module-pickle|pickle]] 模块导出三个类,[[#pickle.Pickler|Pickle]][[#pickle.Unpickler|Unpickler]] [[#pickle.PickleBuffer|PickleBuffer]]
[[#pickle.Unpickler|<code>Unpickler</code>]] and [[#pickle.PickleBuffer|<code>PickleBuffer</code>]]:
 
  
 
<dl>
 
<dl>
<dt>''class'' <code>pickle.</code><code>Pickler</code><span class="sig-paren">(</span>''file'', ''protocol=None'', ''\*'', ''fix_imports=True'', ''buffer_callback=None''<span class="sig-paren">)</span></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">pickle.</span></span><span class="sig-name descname"><span class="pre">Pickler</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">file</span></span>'', ''<span class="n"><span class="pre">protocol</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="o"><span class="pre">*</span></span>'', ''<span class="n"><span class="pre">fix_imports</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span>'', ''<span class="n"><span class="pre">buffer_callback</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>This takes a binary file for writing a pickle data stream.</p>
+
<dd><p>这需要一个二进制文件来编写pickle数据流。</p>
<p>The optional ''protocol'' argument, an integer, tells the pickler to use
+
<p>可选的 ''protocol'' 参数,一个整数,告诉pickler 使用给定的协议; 支持的协议是 0 [[#pickle.HIGHEST_PROTOCOL|HIGHEST_PROTOCOL]]。 如果未指定,则默认值为 [[#pickle.DEFAULT_PROTOCOL|DEFAULT_PROTOCOL]]。 如果指定了负数,则选择 [[#pickle.HIGHEST_PROTOCOL|HIGHEST_PROTOCOL]]</p>
the given protocol; supported protocols are 0 to [[#pickle.HIGHEST_PROTOCOL|<code>HIGHEST_PROTOCOL</code>]].
+
<p>''file'' 参数必须具有接受单个字节参数的 write() 方法。 因此,它可以是为二进制写入而打开的磁盘文件、[[../io#io|io.BytesIO]] 实例或任何其他符合此接口的自定义对象。</p>
If not specified, the default is [[#pickle.DEFAULT_PROTOCOL|<code>DEFAULT_PROTOCOL</code>]]. If a negative
+
<p>如果 ''fix_imports'' true ''protocol'' 小于 3,pickle 将尝试将新的 Python 3 名称映射到 Python 2 中使用的旧模块名称,以便pickle 数据流用 Python 2 可读。</p>
number is specified, [[#pickle.HIGHEST_PROTOCOL|<code>HIGHEST_PROTOCOL</code>]] is selected.</p>
+
<p>如果 ''buffer_callback'' 为 None(默认值),则缓冲区视图将序列化为 ''file'' 作为 pickle 流的一部分。</p>
<p>The ''file'' argument must have a write() method that accepts a single bytes
+
<p>如果 ''buffer_callback'' 不是 None,则可以使用缓冲区视图调用任意次数。 如果回调返回 false 值(例如 None),则给定的缓冲区为 [[#pickle-oob|带外]] ; 否则缓冲区在带内序列化,即 泡菜流里面。</p>
argument. It can thus be an on-disk file opened for binary writing, an
+
<p>如果 ''buffer_callback'' 不是 None 并且 ''protocol'' None 或小于 5,则会出错。</p>
[[../io#io|<code>io.BytesIO</code>]] instance, or any other custom object that meets this
 
interface.</p>
 
<p>If ''fix_imports'' is true and ''protocol'' is less than 3, pickle will try to
 
map the new Python 3 names to the old module names used in Python 2, so
 
that the pickle data stream is readable with Python 2.</p>
 
<p>If ''buffer_callback'' is None (the default), buffer views are
 
serialized into ''file'' as part of the pickle stream.</p>
 
<p>If ''buffer_callback'' is not None, then it can be called any number
 
of times with a buffer view. If the callback returns a false value
 
(such as None), the given buffer is [[#pickle-oob|<span class="std std-ref">out-of-band</span>]];
 
otherwise the buffer is serialized in-band, i.e. inside the pickle stream.</p>
 
<p>It is an error if ''buffer_callback'' is not None and ''protocol'' is
 
None or smaller than 5.</p>
 
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">3.8 版更改: </span>The ''buffer_callback'' argument was added.</p>
+
<p><span class="versionmodified changed"> 3.8 版更改: </span> 添加了 ''buffer_callback'' 参数。</p>
  
 
</div>
 
</div>
 
<dl>
 
<dl>
<dt><code>dump</code><span class="sig-paren">(</span>''<span class="n">obj</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">dump</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">obj</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Write the pickled representation of ''obj'' to the open file object given in
+
<dd><p>''obj'' 的腌制表示写入构造函数中给出的打开文件对象。</p></dd></dl>
the constructor.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>persistent_id</code><span class="sig-paren">(</span>''<span class="n">obj</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">persistent_id</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">obj</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Do nothing by default. This exists so a subclass can override it.</p>
+
<dd><p>默认什么都不做。 它存在以便子类可以覆盖它。</p>
<p>If [[#pickle.Pickler.persistent_id|<code>persistent_id()</code>]] returns <code>None</code>, ''obj'' is pickled as usual. Any
+
<p>如果 [[#pickle.Pickler.persistent_id|persistent_id()]] 返回 <code>None</code>''obj'' 像往常一样被腌制。 任何其他值都会导致 [[#pickle.Pickler|Pickler]] 将返回值作为 ''obj'' 的持久 ID 发出。 这个持久ID的含义应该由[[#pickle.Unpickler.persistent_load|Unpickler.persistent_load()]]定义。 请注意, [[#pickle.Pickler.persistent_id|persistent_id()]] 返回的值本身不能具有持久 ID。</p>
other value causes [[#pickle.Pickler|<code>Pickler</code>]] to emit the returned value as a
+
<p>有关详细信息和使用示例,请参阅 [[#pickle-persistent|外部对象持久性]] </p></dd></dl>
persistent ID for ''obj''. The meaning of this persistent ID should be
 
defined by [[#pickle.Unpickler.persistent_load|<code>Unpickler.persistent_load()</code>]]. Note that the value
 
returned by [[#pickle.Pickler.persistent_id|<code>persistent_id()</code>]] cannot itself have a persistent ID.</p>
 
<p>See [[#pickle-persistent|<span class="std std-ref">Persistence of External Objects</span>]] for details and examples of uses.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>dispatch_table</code></dt>
+
<dt><span class="sig-name descname"><span class="pre">dispatch_table</span></span></dt>
<dd><p>A pickler object's dispatch table is a registry of ''reduction
+
<dd><p>Pickler 对象的调度表是 ''归约函数'' 的注册表,可以使用 [[../copyreg#copyreg|copyreg.pickle()]] 声明。 它是一个映射,其键是类,值是归约函数。 归约函数采用关联类的单个参数,并且应符合与 <code>__reduce__()</code> 方法相同的接口。</p>
functions'' of the kind which can be declared using
+
<p>默认情况下,pickler 对象将没有 [[#pickle.Pickler.dispatch_table|dispatch_table]] 属性,而是使用由 [[../copyreg#module-copyreg|copyreg]] 模块管理的全局调度表。 但是,要为特定的pickler 对象自定义酸洗,可以将 [[#pickle.Pickler.dispatch_table|dispatch_table]] 属性设置为类似 dict 的对象。 或者,如果 [[#pickle.Pickler|Pickler]] 的子类具有 [[#pickle.Pickler.dispatch_table|dispatch_table]] 属性,那么这将用作该类实例的默认调度表。</p>
[[../copyreg#copyreg|<code>copyreg.pickle()</code>]]. It is a mapping whose keys are classes
+
<p>有关用法示例,请参阅 [[#pickle-dispatch|调度表]] </p>
and whose values are reduction functions. A reduction function
 
takes a single argument of the associated class and should
 
conform to the same interface as a <code>__reduce__()</code>
 
method.</p>
 
<p>By default, a pickler object will not have a
 
[[#pickle.Pickler.dispatch_table|<code>dispatch_table</code>]] attribute, and it will instead use the
 
global dispatch table managed by the [[../copyreg#module-copyreg|<code>copyreg</code>]] module.
 
However, to customize the pickling for a specific pickler object
 
one can set the [[#pickle.Pickler.dispatch_table|<code>dispatch_table</code>]] attribute to a dict-like
 
object. Alternatively, if a subclass of [[#pickle.Pickler|<code>Pickler</code>]] has a
 
[[#pickle.Pickler.dispatch_table|<code>dispatch_table</code>]] attribute then this will be used as the
 
default dispatch table for instances of that class.</p>
 
<p>See [[#pickle-dispatch|<span class="std std-ref">Dispatch Tables</span>]] for usage examples.</p>
 
 
<div class="versionadded">
 
<div class="versionadded">
  
<p><span class="versionmodified added">3.3 新版功能.</span></p>
+
<p><span class="versionmodified added">3.3 版中的新功能。</span></p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
 
<dl>
 
<dl>
<dt><code>reducer_override</code><span class="sig-paren">(</span>''<span class="n">self</span>'', ''<span class="n">obj</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">reducer_override</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">self</span></span>'', ''<span class="n"><span class="pre">obj</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Special reducer that can be defined in [[#pickle.Pickler|<code>Pickler</code>]] subclasses. This
+
<dd><p>可以在 [[#pickle.Pickler|Picker]] 子类中定义的特殊减速器。 此方法优先于 [[#pickle.Pickler.dispatch_table|dispatch_table]] 中的任何减速器。 它应该符合与 <code>__reduce__()</code> 方法相同的接口,并且可以选择返回 <code>NotImplemented</code> 以回退 [[#pickle.Pickler.dispatch_table|dispatch_table]] 注册的减速器以腌制 <code>obj</code></p>
method has priority over any reducer in the [[#pickle.Pickler.dispatch_table|<code>dispatch_table</code>]]. It
+
<p>有关详细示例,请参阅 [[#reducer-override|类型、函数和其他对象的自定义缩减]] </p>
should conform to the same interface as a <code>__reduce__()</code> method, and
 
can optionally return <code>NotImplemented</code> to fallback on
 
[[#pickle.Pickler.dispatch_table|<code>dispatch_table</code>]]-registered reducers to pickle <code>obj</code>.</p>
 
<p>For a detailed example, see [[#reducer-override|<span class="std std-ref">Custom Reduction for Types, Functions, and Other Objects</span>]].</p>
 
 
<div class="versionadded">
 
<div class="versionadded">
  
<p><span class="versionmodified added">3.8 新版功能.</span></p>
+
<p><span class="versionmodified added">3.8 版中的新功能。</span></p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
 
<dl>
 
<dl>
<dt><code>fast</code></dt>
+
<dt><span class="sig-name descname"><span class="pre">fast</span></span></dt>
<dd><p>Deprecated. Enable fast mode if set to a true value. The fast mode
+
<dd><p>已弃用。 如果设置为真值,则启用快速模式。 快速模式禁用备忘录的使用,因此通过不生成多余的 PUT 操作码来加速酸洗过程。 它不应该与自引用对象一起使用,否则会导致 [[#pickle.Pickler|Picker]] 无限递归。</p>
disables the usage of memo, therefore speeding the pickling process by not
+
<p>如果您需要更紧凑的泡菜,请使用 [[../pickletools#pickletools|pickletools.optimize()]]</p></dd></dl>
generating superfluous PUT opcodes. It should not be used with
 
self-referential objects, doing otherwise will cause [[#pickle.Pickler|<code>Pickler</code>]] to
 
recurse infinitely.</p>
 
<p>Use [[../pickletools#pickletools|<code>pickletools.optimize()</code>]] if you need more compact pickles.</p></dd></dl>
 
 
</dd></dl>
 
</dd></dl>
  
 
<dl>
 
<dl>
<dt>''class'' <code>pickle.</code><code>Unpickler</code><span class="sig-paren">(</span>''file'', ''\*'', ''fix_imports=True'', ''encoding=&quot;ASCII&quot;'', ''errors=&quot;strict&quot;'', ''buffers=None''<span class="sig-paren">)</span></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">pickle.</span></span><span class="sig-name descname"><span class="pre">Unpickler</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">file</span></span>'', ''<span class="o"><span class="pre">*</span></span>'', ''<span class="n"><span class="pre">fix_imports</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span>'', ''<span class="n"><span class="pre">encoding</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'ASCII'</span></span>'', ''<span class="n"><span class="pre">errors</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">'strict'</span></span>'', ''<span class="n"><span class="pre">buffers</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>This takes a binary file for reading a pickle data stream.</p>
+
<dd><p>这需要一个二进制文件来读取泡菜数据流。</p>
<p>The protocol version of the pickle is detected automatically, so no
+
<p>pickle 的协议版本是自动检测的,因此不需要协议参数。</p>
protocol argument is needed.</p>
+
<p>参数 ''file'' 必须有三个方法,一个采用整数参数的 read() 方法,一个采用缓冲区参数的 readinto() 方法和一个不需要参数的 readline() 方法,如 [ X211X]io.BufferedIOBase 接口。 因此,''file'' 可以是为二进制读取而打开的磁盘文件、[[../io#io|io.BytesIO]] 对象或任何其他符合此接口的自定义对象。</p>
<p>The argument ''file'' must have three methods, a read() method that takes an
+
<p>可选参数 ''fix_imports''''encoding'' ''errors'' 用于控制对 Python 2 生成的 pickle 流的兼容性支持。 如果 ''fix_imports'' 为真,pickle 将尝试将旧的 Python 2 名称映射到 Python 3 中使用的新名称。 ''encoding'' ''errors'' 告诉 pickle 如何解码 Python 2 腌制的 8 位字符串实例; 这些分别默认为 'ASCII' 'strict'''encoding'' 可以是 'bytes' 来读取这些 8 位字符串实例作为字节对象。 需要使用 <code>encoding='latin1'</code> 来取消 NumPy 数组和 [[../datetime#datetime|datetime]][[../datetime#datetime|date]] [[../datetime#datetime|time]] Python 2 酸洗的实例。</p>
integer argument, a readinto() method that takes a buffer argument
+
<p>如果 ''buffers'' 为 None(默认值),则反序列化所需的所有数据都必须包含在 pickle 流中。 这意味着 ''buffer_callback'' 参数在 [[#pickle.Pickler|Pickler]] 被实例化时(或当 [[#pickle.dump|dump()]] [[#pickle.dumps|dumps()]] 被调用时)为 None .</p>
and a readline() method that requires no arguments, as in the
+
<p>如果 ''buffers'' 不是 None,则它应该是启用缓冲区的对象的迭代,每次 pickle 流引用 [[#pickle-oob|带外]] 缓冲区视图时都会消耗该对象。 这些缓冲区是为了给 Pickler 对象的 ''buffer_callback'' 提供的。</p>
[[../io#io|<code>io.BufferedIOBase</code>]] interface. Thus ''file'' can be an on-disk file
 
opened for binary reading, an [[../io#io|<code>io.BytesIO</code>]] object, or any other
 
custom object that meets this interface.</p>
 
<p>The optional arguments ''fix_imports'', ''encoding'' and ''errors'' are used
 
to control compatibility support for pickle stream generated by Python 2.
 
If ''fix_imports'' is true, pickle will try to map the old Python 2 names
 
to the new names used in Python 3. The ''encoding'' and ''errors'' tell
 
pickle how to decode 8-bit string instances pickled by Python 2;
 
these default to 'ASCII' and 'strict', respectively. The ''encoding'' can
 
be 'bytes' to read these 8-bit string instances as bytes objects.
 
Using <code>encoding='latin1'</code> is required for unpickling NumPy arrays and
 
instances of [[../datetime#datetime|<code>datetime</code>]], [[../datetime#datetime|<code>date</code>]] and
 
[[../datetime#datetime|<code>time</code>]] pickled by Python 2.</p>
 
<p>If ''buffers'' is None (the default), then all data necessary for
 
deserialization must be contained in the pickle stream. This means
 
that the ''buffer_callback'' argument was None when a [[#pickle.Pickler|<code>Pickler</code>]]
 
was instantiated (or when [[#pickle.dump|<code>dump()</code>]] or [[#pickle.dumps|<code>dumps()</code>]] was called).</p>
 
<p>If ''buffers'' is not None, it should be an iterable of buffer-enabled
 
objects that is consumed each time the pickle stream references
 
an [[#pickle-oob|<span class="std std-ref">out-of-band</span>]] buffer view. Such buffers have been
 
given in order to the ''buffer_callback'' of a Pickler object.</p>
 
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">3.8 版更改: </span>The ''buffers'' argument was added.</p>
+
<p><span class="versionmodified changed"> 3.8 版更改: </span> 添加了 ''buffers'' 参数。</p>
  
 
</div>
 
</div>
 
<dl>
 
<dl>
<dt><code>load</code><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">load</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
<dd><p>Read the pickled representation of an object from the open file object
+
<dd><p>从构造函数中给出的打开文件对象中读取对象的腌制表示,并返回其中指定的重构对象层次结构。 超过对象的pickle 表示的字节将被忽略。</p></dd></dl>
given in the constructor, and return the reconstituted object hierarchy
 
specified therein. Bytes past the pickled representation of the object
 
are ignored.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>persistent_load</code><span class="sig-paren">(</span>''<span class="n">pid</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">persistent_load</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">pid</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Raise an [[#pickle.UnpicklingError|<code>UnpicklingError</code>]] by default.</p>
+
<dd><p>默认情况下引发 [[#pickle.UnpicklingError|UnpicklingError]]</p>
<p>If defined, [[#pickle.Unpickler.persistent_load|<code>persistent_load()</code>]] should return the object specified by
+
<p>如果已定义,[[#pickle.Unpickler.persistent_load|persistent_load()]] 应返回由持久 ID ''pid'' 指定的对象。 如果遇到无效的持久 ID,则应引发 [[#pickle.UnpicklingError|UnpicklingError]]</p>
the persistent ID ''pid''. If an invalid persistent ID is encountered, an
+
<p>有关详细信息和使用示例,请参阅 [[#pickle-persistent|外部对象持久性]] </p></dd></dl>
[[#pickle.UnpicklingError|<code>UnpicklingError</code>]] should be raised.</p>
 
<p>See [[#pickle-persistent|<span class="std std-ref">Persistence of External Objects</span>]] for details and examples of uses.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>find_class</code><span class="sig-paren">(</span>''<span class="n">module</span>'', ''<span class="n">name</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">find_class</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">module</span></span>'', ''<span class="n"><span class="pre">name</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Import ''module'' if necessary and return the object called ''name'' from it,
+
<dd><p>如有必要,导入 ''module'' 并从中返回名为 ''name'' 的对象,其中 ''module'' ''name'' 参数为 [[../stdtypes#str|str]] ] 对象。 请注意,与其名称所暗示的不同,[[#pickle.Unpickler.find_class|find_class()]] 也用于查找函数。</p>
where the ''module'' and ''name'' arguments are [[../stdtypes#str|<code>str</code>]] objects. Note,
+
<p>子类可以覆盖它以控制对象的类型和加载方式,从而潜在地降低安全风险。 有关详细信息,请参阅 [[#pickle-restrict|限制全局变量]] </p></dd></dl>
unlike its name suggests, [[#pickle.Unpickler.find_class|<code>find_class()</code>]] is also used for finding
 
functions.</p>
 
<p>Subclasses may override this to gain control over what type of objects and
 
how they can be loaded, potentially reducing security risks. Refer to
 
[[#pickle-restrict|<span class="std std-ref">Restricting Globals</span>]] for details.</p>
 
<p>Raises an [[../sys#auditing|<span class="std std-ref">auditing event</span>]] <code>pickle.find_class</code> with arguments <code>module</code>, <code>name</code>.</p></dd></dl>
 
 
</dd></dl>
 
</dd></dl>
  
 
<dl>
 
<dl>
<dt>''class'' <code>pickle.</code><code>PickleBuffer</code><span class="sig-paren">(</span>''<span class="n">buffer</span>''<span class="sig-paren">)</span></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">pickle.</span></span><span class="sig-name descname"><span class="pre">PickleBuffer</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">buffer</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>A wrapper for a buffer representing picklable data. ''buffer'' must be a
+
<dd><p>表示可腌制数据的缓冲区的包装器。 ''buffer'' 必须是一个 [[../../c-api/buffer#bufferobjects|buffer-providing]] 对象,比如一个 [[../../glossary#term-bytes-like-object|bytes-like object]] 或者一个 N 维数组。</p>
[[../../c-api/buffer#bufferobjects|<span class="std std-ref">buffer-providing</span>]] object, such as a
+
<p>[[#pickle.PickleBuffer|PickleBuffer]] 本身就是一个缓冲区提供者,因此可以将它传递给其他需要缓冲区提供对象的 API,例如 [[../stdtypes#memoryview|memoryview]]</p>
[[../../glossary#term-bytes-like-object|<span class="xref std std-term">bytes-like object</span>]] or a N-dimensional array.</p>
+
<p>[[#pickle.PickleBuffer|PickleBuffer]] 对象只能使用 pickle 协议 5 或更高版本进行序列化。 它们有资格进行 [[#pickle-oob|带外序列化]] </p>
<p>[[#pickle.PickleBuffer|<code>PickleBuffer</code>]] is itself a buffer provider, therefore it is
 
possible to pass it to other APIs expecting a buffer-providing object,
 
such as [[../stdtypes#memoryview|<code>memoryview</code>]].</p>
 
<p>[[#pickle.PickleBuffer|<code>PickleBuffer</code>]] objects can only be serialized using pickle
 
protocol 5 or higher. They are eligible for
 
[[#pickle-oob|<span class="std std-ref">out-of-band serialization</span>]].</p>
 
 
<div class="versionadded">
 
<div class="versionadded">
  
<p><span class="versionmodified added">3.8 新版功能.</span></p>
+
<p><span class="versionmodified added">3.8 版中的新功能。</span></p>
  
 
</div>
 
</div>
 
<dl>
 
<dl>
<dt><code>raw</code><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">raw</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
<dd><p>Return a [[../stdtypes#memoryview|<code>memoryview</code>]] of the memory area underlying this buffer.
+
<dd><p>返回此缓冲区下的内存区域的 [[../stdtypes#memoryview|memoryview]]。 返回的对象是格式为 <code>B</code>(无符号字节)的一维 C 连续内存视图。 [[../exceptions#BufferError|BufferError]] 如果缓冲区既不是 C 连续的,也不是 Fortran 连续的,则会引发。</p></dd></dl>
The returned object is a one-dimensional, C-contiguous memoryview
 
with format <code>B</code> (unsigned bytes). [[../exceptions#BufferError|<code>BufferError</code>]] is raised if
 
the buffer is neither C- nor Fortran-contiguous.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>release</code><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">release</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
<dd><p>Release the underlying buffer exposed by the PickleBuffer object.</p></dd></dl>
+
<dd><p>释放由 PickleBuffer 对象公开的底层缓冲区。</p></dd></dl>
 
</dd></dl>
 
</dd></dl>
  
第447行: 第291行:
  
 
<span id="pickle-picklable"></span>
 
<span id="pickle-picklable"></span>
== What can be pickled and unpickled? ==
+
== 什么可以腌制和不腌制? ==
  
The following types can be pickled:
+
可以腌制以下类型:
  
* <code>None</code>, <code>True</code>, and <code>False</code>
+
* <code>None</code><code>True</code> <code>False</code>
* integers, floating point numbers, complex numbers
+
* 整数、浮点数、复数
* strings, bytes, bytearrays
+
* 字符串、字节、字节数组
* tuples, lists, sets, and dictionaries containing only picklable objects
+
* 仅包含可picklable 对象的元组、列表、集合和字典
* functions defined at the top level of a module (using [[../../reference/compound_stmts#def|<code>def</code>]], not [[../../reference/expressions#lambda|<code>lambda</code>]])
+
* 在模块顶层定义的函数(使用 [[../../reference/compound_stmts#def|def]],而不是 [[../../reference/expressions#lambda|lambda]]
* 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 [[../stdtypes#object|<code>__dict__</code>]] or the result of calling <code>__getstate__()</code> is picklable (see section [[#pickle-inst|<span class="std std-ref">Pickling Class Instances</span>]] for details).
+
* [[../stdtypes#object|__dict__]] 或调用 <code>__getstate__()</code> 的结果是可酸洗的类的实例(有关详细信息,请参阅 [[#pickle-inst|酸洗类实例]] 部分)。
  
Attempts to pickle unpicklable objects will raise the [[#pickle.PicklingError|<code>PicklingError</code>]]
+
尝试腌制不可腌制的对象将引发 [[#pickle.PicklingError|PicklingError]] 异常; 发生这种情况时,可能已经将未指定数量的字节写入底层文件。 尝试腌制一个高度递归的数据结构可能会超过最大递归深度,在这种情况下将引发 [[../exceptions#RecursionError|RecursionError]]。 您可以使用 [[../sys#sys|sys.setrecursionlimit()]] 小心地提高此限制。
exception; when this happens, an unspecified number of bytes may have already
 
been written to the underlying file. Trying to pickle a highly recursive data
 
structure may exceed the maximum recursion depth, a [[../exceptions#RecursionError|<code>RecursionError</code>]] will be
 
raised in this case. You can carefully raise this limit with
 
[[../sys#sys|<code>sys.setrecursionlimit()</code>]].
 
  
Note that functions (built-in and user-defined) are pickled by &quot;fully qualified&quot;
+
请注意,函数(内置和用户定义的)由“完全限定”名称引用而不是值来腌制。 [[#id10|2]] 这意味着只腌制函数名称,以及定义函数的模块名称。 函数的代码及其任何函数属性都不会被腌制。 因此定义模块必须在 unpickling 环境中可导入,并且模块必须包含命名对象,否则将引发异常。 [[#id11|3]]
name reference, not by value. [[#id8|2]] This means that only the function name is
 
pickled, along with the name of the module the function is defined in. Neither
 
the function's code, nor any of its function attributes are pickled. Thus the
 
defining module must be importable in the unpickling environment, and the module
 
must contain the named object, otherwise an exception will be raised. [[#id9|3]]
 
  
Similarly, classes are pickled by named reference, so the same restrictions in
+
类似地,类通过命名引用进行酸洗,因此在 unpickling 环境中适用相同的限制。 请注意,类的代码或数据均未经过酸洗,因此在以下示例中,类属性 <code>attr</code> unpickling 环境中不会恢复:
the unpickling environment apply. Note that none of the class's code or data is
 
pickled, so in the following example the class attribute <code>attr</code> is not
 
restored in the unpickling environment:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第483行: 第314行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>class Foo:
+
<syntaxhighlight lang="python3">class Foo:
 
     attr = 'A class attribute'
 
     attr = 'A class attribute'
  
picklestring = pickle.dumps(Foo)</pre>
+
picklestring = pickle.dumps(Foo)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
These restrictions are why picklable functions and classes must be defined in
+
这些限制就是为什么必须在模块的顶层定义可腌制的函数和类。
the top level of a module.
 
  
Similarly, when class instances are pickled, their class's code and data are not
+
类似地,当类实例被腌制时,它们的类的代码和数据不会与它们一起被腌制。 只有实例数据被腌制。 这是故意完成的,因此您可以修复类中的错误或向类添加方法,并且仍然加载使用早期版本的类创建的对象。 如果您计划拥有将看到一个类的多个版本的长期对象,那么在对象中放置一个版本号可能是值得的,以便可以通过类的 <code>__setstate__()</code> 方法进行适当的转换。
pickled along with them. Only the instance data are pickled. This is done on
 
purpose, so you can fix bugs in a class or add methods to the class and still
 
load objects that were created with an earlier version of the class. If you
 
plan to have long-lived objects that will see many versions of a class, it may
 
be worthwhile to put a version number in the objects so that suitable
 
conversions can be made by the class's <code>__setstate__()</code> method.
 
  
  
第507行: 第331行:
  
 
<span id="pickle-inst"></span>
 
<span id="pickle-inst"></span>
== Pickling Class Instances ==
+
== 酸洗类实例 ==
  
In this section, we describe the general mechanisms available to you to define,
+
在本节中,我们将描述可用于定义、自定义和控制类实例的pickle 和unpickle 方式的一般机制。
customize, and control how class instances are pickled and unpickled.
 
  
In most cases, no additional code is needed to make instances picklable. By
+
在大多数情况下,不需要额外的代码来使实例可以pickle。 默认情况下,pickle 将通过自省检索实例的类和属性。 当一个类实例被 unpickled 时,它的 <code>__init__()</code> 方法通常是 ''not'' 调用。 默认行为首先创建一个未初始化的实例,然后恢复保存的属性。 以下代码显示了此行为的实现:
default, pickle will retrieve the class and the attributes of an instance via
 
introspection. When a class instance is unpickled, its <code>__init__()</code> method
 
is usually ''not'' invoked. The default behaviour first creates an uninitialized
 
instance and then restores the saved attributes. The following code shows an
 
implementation of this behaviour:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第523行: 第341行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>def save(obj):
+
<syntaxhighlight lang="python3">def save(obj):
 
     return (obj.__class__, obj.__dict__)
 
     return (obj.__class__, obj.__dict__)
  
第529行: 第347行:
 
     obj = cls.__new__(cls)
 
     obj = cls.__new__(cls)
 
     obj.__dict__.update(attributes)
 
     obj.__dict__.update(attributes)
     return obj</pre>
+
     return obj</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Classes can alter the default behaviour by providing one or several special
+
类可以通过提供一种或几种特殊方法来改变默认行为:
methods:
 
  
 
<dl>
 
<dl>
<dt><code>object.</code><code>__getnewargs_ex__</code><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">object.</span></span><span class="sig-name descname"><span class="pre">__getnewargs_ex__</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
<dd><p>In protocols 2 and newer, classes that implements the
+
<dd><p>在协议 2 和更新的协议中,实现 [[#object.__getnewargs_ex__|__getnewargs_ex__()]] 方法的类可以在 unpickling 时指定传递给 [[../../reference/datamodel#object|__new__()]] 方法的值。 该方法必须返回一对 <code>(args, kwargs)</code>,其中 ''args'' 是位置参数的元组,而 ''kwargs'' 是用于构造对象的命名参数字典。 这些将在 unpickling 时传递给 [[../../reference/datamodel#object|__new__()]] 方法。</p>
[[#object.__getnewargs_ex__|<code>__getnewargs_ex__()</code>]] method can dictate the values passed to the
+
<p>如果您的类的 [[../../reference/datamodel#object|__new__()]] 方法需要仅关键字参数,则您应该实现此方法。 否则,为了兼容性,建议实现 [[#object.__getnewargs__|__getnewargs__()]]</p>
[[../../reference/datamodel#object|<code>__new__()</code>]] method upon unpickling. The method must return a pair
 
<code>(args, kwargs)</code> where ''args'' is a tuple of positional arguments
 
and ''kwargs'' a dictionary of named arguments for constructing the
 
object. Those will be passed to the [[../../reference/datamodel#object|<code>__new__()</code>]] method upon
 
unpickling.</p>
 
<p>You should implement this method if the [[../../reference/datamodel#object|<code>__new__()</code>]] method of your
 
class requires keyword-only arguments. Otherwise, it is recommended for
 
compatibility to implement [[#object.__getnewargs__|<code>__getnewargs__()</code>]].</p>
 
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">3.6 版更改: </span>[[#object.__getnewargs_ex__|<code>__getnewargs_ex__()</code>]] is now used in protocols 2 and 3.</p>
+
<p><span class="versionmodified changed"> 3.6 版更改: </span>[[#object.__getnewargs_ex__|__getnewargs_ex__()]] 现在用于协议 2 和 3。</p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
 
<dl>
 
<dl>
<dt><code>object.</code><code>__getnewargs__</code><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">object.</span></span><span class="sig-name descname"><span class="pre">__getnewargs__</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
<dd><p>This method serves a similar purpose as [[#object.__getnewargs_ex__|<code>__getnewargs_ex__()</code>]], but
+
<dd><p>此方法的用途与 [[#object.__getnewargs_ex__|__getnewargs_ex__()]] 类似,但仅支持位置参数。 它必须返回一个参数元组 <code>args</code>,该元组将在解压时传递给 [[../../reference/datamodel#object|__new__()]] 方法。</p>
supports only positional arguments. It must return a tuple of arguments
+
<p>如果定义了 [[#object.__getnewargs_ex__|__getnewargs_ex__()]],则不会调用 [[#object.__getnewargs__|__getnewargs__()]]</p>
<code>args</code> which will be passed to the [[../../reference/datamodel#object|<code>__new__()</code>]] method upon unpickling.</p>
 
<p>[[#object.__getnewargs__|<code>__getnewargs__()</code>]] will not be called if [[#object.__getnewargs_ex__|<code>__getnewargs_ex__()</code>]] is
 
defined.</p>
 
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">3.6 版更改: </span>Before Python 3.6, [[#object.__getnewargs__|<code>__getnewargs__()</code>]] was called instead of
+
<p><span class="versionmodified changed"> 3.6 版更改: </span> Python 3.6 之前, [[#object.__getnewargs__|__getnewargs__()]] 在协议 2 和 3 中被调用而不是 [[#object.__getnewargs_ex__|__getnewargs_ex__()]]</p>
[[#object.__getnewargs_ex__|<code>__getnewargs_ex__()</code>]] in protocols 2 and 3.</p>
 
  
 
</div></dd></dl>
 
</div></dd></dl>
  
; <code>object.</code><code>__getstate__</code><span class="sig-paren">(</span><span class="sig-paren">)</span>
+
; <span class="sig-prename descclassname"><span class="pre">object.</span></span><span class="sig-name descname"><span class="pre">__getstate__</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span>
: Classes can further influence how their instances are pickled; if the class defines the method [[#object.__getstate__|<code>__getstate__()</code>]], it is called and the returned object is pickled as the contents for the instance, instead of the contents of the instance's dictionary. If the [[#object.__getstate__|<code>__getstate__()</code>]] method is absent, the instance's [[../stdtypes#object|<code>__dict__</code>]] is pickled as usual.
+
: 类可以进一步影响它们的实例如何被腌制; 如果类定义了 [[#object.__getstate__|__getstate__()]] 方法,则调用该方法并将返回的对象作为实例的内容进行腌制,而不是实例字典的内容。 如果 [[#object.__getstate__|__getstate__()]] 方法不存在,则实例的 [[../stdtypes#object|__dict__]] 像往常一样被腌制。
  
 
<dl>
 
<dl>
<dt><code>object.</code><code>__setstate__</code><span class="sig-paren">(</span>''<span class="n">state</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">object.</span></span><span class="sig-name descname"><span class="pre">__setstate__</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">state</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Upon unpickling, if the class defines [[#object.__setstate__|<code>__setstate__()</code>]], it is called with
+
<dd><p>unpickling 时,如果该类定义了 [[#object.__setstate__|__setstate__()]],则以 unpickled 状态调用它。 在这种情况下,状态对象不需要是字典。 否则,pickled 状态必须是一个字典,并且它的项被分配给新实例的字典。</p>
the unpickled state. In that case, there is no requirement for the state
 
object to be a dictionary. Otherwise, the pickled state must be a dictionary
 
and its items are assigned to the new instance's dictionary.</p>
 
 
<div class="admonition note">
 
<div class="admonition note">
  
<p>注解</p>
+
<p>笔记</p>
<p>If [[#object.__getstate__|<code>__getstate__()</code>]] returns a false value, the [[#object.__setstate__|<code>__setstate__()</code>]]
+
<p>如果 [[#object.__getstate__|__getstate__()]] 返回一个假值,[[#object.__setstate__|__setstate__()]] 方法在 unpickling 时不会被调用。</p>
method will not be called upon unpickling.</p>
 
  
 
</div></dd></dl>
 
</div></dd></dl>
  
Refer to the section [[#pickle-state|<span class="std std-ref">Handling Stateful Objects</span>]] for more information about how to use
+
有关如何使用方法 <code>__getstate__()</code> <code>__setstate__()</code> 的更多信息,请参阅 [[#pickle-state|处理有状态对象]] 部分。
the methods <code>__getstate__()</code> and <code>__setstate__()</code>.
 
  
 
<div class="admonition note">
 
<div class="admonition note">
  
注解
+
笔记
  
At unpickling time, some methods like <code>__getattr__()</code>,
+
unpickling 时,可能会在实例上调用一些方法,如 <code>__getattr__()</code><code>__getattribute__()</code> <code>__setattr__()</code>。 如果这些方法依赖于某些内部不变量为真,则该类型应实现 <code>__new__()</code> 来建立这样的不变量,因为在取消实例时不会调用 <code>__init__()</code>
<code>__getattribute__()</code>, or <code>__setattr__()</code> may be called upon the
 
instance. In case those methods rely on some internal invariant being
 
true, the type should implement <code>__new__()</code> to establish such an
 
invariant, as <code>__init__()</code> is not called when unpickling an
 
instance.
 
  
  
 
</div>
 
</div>
As we shall see, pickle does not use directly the methods described above. In
+
正如我们将看到的,pickle 不直接使用上述方法。 事实上,这些方法是实现 <code>__reduce__()</code> 特殊方法的复制协议的一部分。 复制协议提供了一个统一的接口,用于检索酸洗和复制对象所需的数据。 [[#id12|4]]
fact, these methods are part of the copy protocol which implements the
 
<code>__reduce__()</code> special method. The copy protocol provides a unified
 
interface for retrieving the data necessary for pickling and copying
 
objects. [[#id10|4]]
 
  
Although powerful, implementing <code>__reduce__()</code> directly in your classes is
+
尽管功能强大,但直接在类中实现 <code>__reduce__()</code> 很容易出错。 因此,类设计者应尽可能使用高级接口(即 <code>__getnewargs_ex__()</code><code>__getstate__()</code> <code>__setstate__()</code>)。 然而,我们将展示使用 <code>__reduce__()</code> 是唯一选择或导致更有效酸洗或两者兼而有之的情况。
error prone. For this reason, class designers should use the high-level
 
interface (i.e., <code>__getnewargs_ex__()</code>, <code>__getstate__()</code> and
 
<code>__setstate__()</code>) whenever possible. We will show, however, cases where
 
using <code>__reduce__()</code> is the only option or leads to more efficient pickling
 
or both.
 
  
 
<dl>
 
<dl>
<dt><code>object.</code><code>__reduce__</code><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">object.</span></span><span class="sig-name descname"><span class="pre">__reduce__</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
<dd><p>The interface is currently defined as follows. The [[#object.__reduce__|<code>__reduce__()</code>]] method
+
<dd><p>该接口目前定义如下。 [[#object.__reduce__|__reduce__()]] 方法不接受任何参数,并且应该返回一个字符串或者最好是一个元组(返回的对象通常被称为“reduce 值”)。</p>
takes no argument and shall return either a string or preferably a tuple (the
+
<p>如果返回字符串,则该字符串应被解释为全局变量的名称。 它应该是对象相对于其模块的本地名称; pickle 模块搜索模块命名空间以确定对象的模块。 此行为通常对单身人士有用。</p>
returned object is often referred to as the &quot;reduce value&quot;).</p>
+
<p>返回元组时,它的长度必须介于 2 到 6 个项目之间。 可以省略可选项目,也可以提供 <code>None</code> 作为它们的值。 每个项目的语义按顺序排列:</p>
<p>If a string is returned, the string should be interpreted as the name of a
 
global variable. It should be the object's local name relative to its
 
module; the pickle module searches the module namespace to determine the
 
object's module. This behaviour is typically useful for singletons.</p>
 
<p>When a tuple is returned, it must be between two and six items long.
 
Optional items can either be omitted, or <code>None</code> can be provided as their
 
value. The semantics of each item are in order:</p>
 
 
<ul>
 
<ul>
<li><p>A callable object that will be called to create the initial version of the
+
<li><p>一个可调用对象,将被调用以创建对象的初始版本。</p></li>
object.</p></li>
+
<li><p>可调用对象的参数元组。 如果可调用对象不接受任何参数,则必须给出一个空元组。</p></li>
<li><p>A tuple of arguments for the callable object. An empty tuple must be given
+
<li><p>可选地,对象的状态,将传递给对象的 [[#object.__setstate__|__setstate__()]] 方法,如前所述。 如果对象没有这样的方法,那么该值必须是一个字典,它将被添加到对象的 [[../stdtypes#object|__dict__]] 属性中。</p></li>
if the callable does not accept any argument.</p></li>
+
<li><p>可选地,一个迭代器(而不是一个序列)产生连续的项目。 这些项目将使用 <code>obj.append(item)</code> 或批量使用 <code>obj.extend(list_of_items)</code> 附加到对象。 这主要用于列表子类,但也可以被其他类使用,只要它们具有带有适当签名的 <code>append()</code> <code>extend()</code> 方法。 (使用 <code>append()</code> 还是 <code>extend()</code> 取决于使用的 pickle 协议版本以及要追加的项数,因此两者都必须支持。)</p></li>
<li><p>Optionally, the object's state, which will be passed to the object's
+
<li><p>可选地,迭代器(不是序列)产生连续的键值对。 这些项目将使用 <code>obj[key] = value</code> 存储到对象中。 这主要用于字典子类,但也可以被其他类使用,只要它们实现 [[../../reference/datamodel#object|__setitem__()]]</p></li>
[[#object.__setstate__|<code>__setstate__()</code>]] method as previously described. If the object has no
+
<li><p>可选地,具有 <code>(obj, state)</code> 签名的可调用对象。 这个可调用对象允许用户以编程方式控制特定对象的状态更新行为,而不是使用 <code>obj</code> 的静态 [[#object.__setstate__|__setstate__()]] 方法。 如果不是 <code>None</code>,这个可调用对象将优先于 <code>obj</code> [[#object.__setstate__|__setstate__()]]</p>
such method then, the value must be a dictionary and it will be added to
 
the object's [[../stdtypes#object|<code>__dict__</code>]] attribute.</p></li>
 
<li><p>Optionally, an iterator (and not a sequence) yielding successive items.
 
These items will be appended to the object either using
 
<code>obj.append(item)</code> or, in batch, using <code>obj.extend(list_of_items)</code>.
 
This is primarily used for list subclasses, but may be used by other
 
classes as long as they have <code>append()</code> and <code>extend()</code> methods with
 
the appropriate signature. (Whether <code>append()</code> or <code>extend()</code> is
 
used depends on which pickle protocol version is used as well as the number
 
of items to append, so both must be supported.)</p></li>
 
<li><p>Optionally, an iterator (not a sequence) yielding successive key-value
 
pairs. These items will be stored to the object using <code>obj[key] = value</code>. This is primarily used for dictionary subclasses, but may be used
 
by other classes as long as they implement [[../../reference/datamodel#object|<code>__setitem__()</code>]].</p></li>
 
<li><p>Optionally, a callable with a <code>(obj, state)</code> signature. This
 
callable allows the user to programmatically control the state-updating
 
behavior of a specific object, instead of using <code>obj</code>'s static
 
[[#object.__setstate__|<code>__setstate__()</code>]] method. If not <code>None</code>, this callable will have
 
priority over <code>obj</code>'s [[#object.__setstate__|<code>__setstate__()</code>]].</p>
 
 
<div class="versionadded">
 
<div class="versionadded">
  
<p><span class="versionmodified added">3.8 新版功能: </span>The optional sixth tuple item, <code>(obj, state)</code>, was added.</p>
+
<p><span class="versionmodified added">3.8 新功能:</span>增加了可选的第六个元组项,<code>(obj, state)</code></p>
  
 
</div></li></ul>
 
</div></li></ul>
 
</dd></dl>
 
</dd></dl>
  
; <code>object.</code><code>__reduce_ex__</code><span class="sig-paren">(</span>''<span class="n">protocol</span>''<span class="sig-paren">)</span>
+
; <span class="sig-prename descclassname"><span class="pre">object.</span></span><span class="sig-name descname"><span class="pre">__reduce_ex__</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">protocol</span></span>''<span class="sig-paren">)</span>
: Alternatively, a [[#object.__reduce_ex__|<code>__reduce_ex__()</code>]] method may be defined. The only difference is this method should take a single integer argument, the protocol version. When defined, pickle will prefer it over the [[#object.__reduce__|<code>__reduce__()</code>]] method. In addition, [[#object.__reduce__|<code>__reduce__()</code>]] automatically becomes a synonym for the extended version. The main use for this method is to provide backwards-compatible reduce values for older Python releases.
+
: 或者,可以定义 [[#object.__reduce_ex__|__reduce_ex__()]] 方法。 唯一的区别是此方法应采用单个整数参数,即协议版本。 定义后,pickle 会比 [[#object.__reduce__|__reduce__()]] 方法更喜欢它。 此外,[[#object.__reduce__|__reduce__()]] 自动成为扩展版本的同义词。 此方法的主要用途是为较旧的 Python 版本提供向后兼容的 reduce 值。
  
 
<div id="persistence-of-external-objects" class="section">
 
<div id="persistence-of-external-objects" class="section">
  
 
<span id="pickle-persistent"></span>
 
<span id="pickle-persistent"></span>
=== Persistence of External Objects ===
+
=== 外部对象的持久性 ===
  
For the benefit of object persistence, the [[#module-pickle|<code>pickle</code>]] module supports the
+
为了对象持久性的好处,[[#module-pickle|pickle]] 模块支持对pickle 数据流之外的对象的引用的概念。 此类对象由持久 ID 引用,该 ID 应该是一串字母数字字符(对于协议 0)[[#id13|5]] 或只是一个任意对象(对于任何更新的协议)。
notion of a reference to an object outside the pickled data stream. Such
 
objects are referenced by a persistent ID, which should be either a string of
 
alphanumeric characters (for protocol 0) [[#id11|5]] or just an arbitrary object (for
 
any newer protocol).
 
  
The resolution of such persistent IDs is not defined by the [[#module-pickle|<code>pickle</code>]]
+
[[#module-pickle|pickle]] 模块未定义此类持久 ID 的解析; 它将将此分辨率委托给pickler 和unpickler 上的用户定义方法,分别为[[#pickle.Pickler.persistent_id|persistent_id()]] [[#pickle.Unpickler.persistent_load|persistent_load()]]
module; it will delegate this resolution to the user-defined methods on the
 
pickler and unpickler, [[#pickle.Pickler.persistent_id|<code>persistent_id()</code>]] and
 
[[#pickle.Unpickler.persistent_load|<code>persistent_load()</code>]] respectively.
 
  
To pickle objects that have an external persistent ID, the pickler must have a
+
要pickle具有外部持久ID的对象,pickler必须有一个自定义的[[#pickle.Pickler.persistent_id|persistent_id()]]方法,该方法将一个对象作为参数并返回<code>None</code>或该对象的持久ID。 当返回 <code>None</code> 时,pickler 只是像平常一样腌制对象。 当返回一个持久 ID 字符串时,pickler 将pickle 该对象以及一个标记,以便 unpickler 将其识别为持久 ID。
custom [[#pickle.Pickler.persistent_id|<code>persistent_id()</code>]] method that takes an object as an
 
argument and returns either <code>None</code> or the persistent ID for that object.
 
When <code>None</code> is returned, the pickler simply pickles the object as normal.
 
When a persistent ID string is returned, the pickler will pickle that object,
 
along with a marker so that the unpickler will recognize it as a persistent ID.
 
  
To unpickle external objects, the unpickler must have a custom
+
要解开外部对象,解开器必须有一个自定义的 [[#pickle.Unpickler.persistent_load|persistent_load()]] 方法,该方法接受一个持久 ID 对象并返回引用的对象。
[[#pickle.Unpickler.persistent_load|<code>persistent_load()</code>]] method that takes a persistent ID object and
 
returns the referenced object.
 
  
Here is a comprehensive example presenting how persistent ID can be used to
+
这是一个综合示例,展示了如何使用持久 ID 通过引用来pickle外部对象。
pickle external objects by reference.
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第696行: 第442行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre># Simple example presenting how persistent ID can be used to pickle
+
<syntaxhighlight lang="python3"># Simple example presenting how persistent ID can be used to pickle
 
# external objects by reference.
 
# external objects by reference.
  
第704行: 第450行:
  
 
# Simple class representing a record in our database.
 
# Simple class representing a record in our database.
MemoRecord = namedtuple(&quot;MemoRecord&quot;, &quot;key, task&quot;)
+
MemoRecord = namedtuple("MemoRecord", "key, task")
  
 
class DBPickler(pickle.Pickler):
 
class DBPickler(pickle.Pickler):
第714行: 第460行:
 
             # Here, our persistent ID is simply a tuple, containing a tag and a
 
             # Here, our persistent ID is simply a tuple, containing a tag and a
 
             # key, which refers to a specific record in the database.
 
             # key, which refers to a specific record in the database.
             return (&quot;MemoRecord&quot;, obj.key)
+
             return ("MemoRecord", obj.key)
 
         else:
 
         else:
 
             # If obj does not have a persistent ID, return None. This means obj
 
             # If obj does not have a persistent ID, return None. This means obj
第732行: 第478行:
 
         cursor = self.connection.cursor()
 
         cursor = self.connection.cursor()
 
         type_tag, key_id = pid
 
         type_tag, key_id = pid
         if type_tag == &quot;MemoRecord&quot;:
+
         if type_tag == "MemoRecord":
 
             # Fetch the referenced record from the database and return it.
 
             # Fetch the referenced record from the database and return it.
             cursor.execute(&quot;SELECT * FROM memos WHERE key=?&quot;, (str(key_id),))
+
             cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),))
 
             key, task = cursor.fetchone()
 
             key, task = cursor.fetchone()
 
             return MemoRecord(key, task)
 
             return MemoRecord(key, task)
第741行: 第487行:
 
             # Otherwise, the unpickler will think None is the object referenced
 
             # Otherwise, the unpickler will think None is the object referenced
 
             # by the persistent ID.
 
             # by the persistent ID.
             raise pickle.UnpicklingError(&quot;unsupported persistent object&quot;)
+
             raise pickle.UnpicklingError("unsupported persistent object")
  
  
第749行: 第495行:
  
 
     # Initialize and populate our database.
 
     # Initialize and populate our database.
     conn = sqlite3.connect(&quot;:memory:&quot;)
+
     conn = sqlite3.connect(":memory:")
 
     cursor = conn.cursor()
 
     cursor = conn.cursor()
     cursor.execute(&quot;CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)&quot;)
+
     cursor.execute("CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)")
 
     tasks = (
 
     tasks = (
 
         'give food to fish',
 
         'give food to fish',
第758行: 第504行:
 
         )
 
         )
 
     for task in tasks:
 
     for task in tasks:
         cursor.execute(&quot;INSERT INTO memos VALUES(NULL, ?)&quot;, (task,))
+
         cursor.execute("INSERT INTO memos VALUES(NULL, ?)", (task,))
  
 
     # Fetch the records to be pickled.
 
     # Fetch the records to be pickled.
     cursor.execute(&quot;SELECT * FROM memos&quot;)
+
     cursor.execute("SELECT * FROM memos")
 
     memos = [MemoRecord(key, task) for key, task in cursor]
 
     memos = [MemoRecord(key, task) for key, task in cursor]
 
     # Save the records using our custom DBPickler.
 
     # Save the records using our custom DBPickler.
第767行: 第513行:
 
     DBPickler(file).dump(memos)
 
     DBPickler(file).dump(memos)
  
     print(&quot;Pickled records:&quot;)
+
     print("Pickled records:")
 
     pprint.pprint(memos)
 
     pprint.pprint(memos)
  
 
     # Update a record, just for good measure.
 
     # Update a record, just for good measure.
     cursor.execute(&quot;UPDATE memos SET task='learn italian' WHERE key=1&quot;)
+
     cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1")
  
 
     # Load the records from the pickle data stream.
 
     # Load the records from the pickle data stream.
第777行: 第523行:
 
     memos = DBUnpickler(file, conn).load()
 
     memos = DBUnpickler(file, conn).load()
  
     print(&quot;Unpickled records:&quot;)
+
     print("Unpickled records:")
 
     pprint.pprint(memos)
 
     pprint.pprint(memos)
  
  
 
if __name__ == '__main__':
 
if __name__ == '__main__':
     main()</pre>
+
     main()</syntaxhighlight>
  
 
</div>
 
</div>
第792行: 第538行:
  
 
<span id="pickle-dispatch"></span>
 
<span id="pickle-dispatch"></span>
=== Dispatch Tables ===
+
=== 调度表 ===
  
If one wants to customize pickling of some classes without disturbing
+
如果您想自定义某些类的酸洗而不干扰任何其他依赖酸洗的代码,那么您可以创建一个带有私有调度表的酸洗器。
any other code which depends on pickling, then one can create a
 
pickler with a private dispatch table.
 
  
The global dispatch table managed by the [[../copyreg#module-copyreg|<code>copyreg</code>]] module is
+
[[../copyreg#module-copyreg|copyreg]] 模块管理的全局调度表可作为 <code>copyreg.dispatch_table</code> 使用。 因此,可以选择使用 <code>copyreg.dispatch_table</code> 的修改副本作为私有调度表。
available as <code>copyreg.dispatch_table</code>. Therefore, one may
 
choose to use a modified copy of <code>copyreg.dispatch_table</code> as a
 
private dispatch table.
 
  
For example
+
例如
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第809行: 第550行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>f = io.BytesIO()
+
<syntaxhighlight lang="python3">f = io.BytesIO()
 
p = pickle.Pickler(f)
 
p = pickle.Pickler(f)
 
p.dispatch_table = copyreg.dispatch_table.copy()
 
p.dispatch_table = copyreg.dispatch_table.copy()
p.dispatch_table[SomeClass] = reduce_SomeClass</pre>
+
p.dispatch_table[SomeClass] = reduce_SomeClass</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
creates an instance of [[#pickle.Pickler|<code>pickle.Pickler</code>]] with a private dispatch
+
创建一个 [[#pickle.Pickler|pickle.Pickler]] 的实例,带有一个专门处理 <code>SomeClass</code> 类的私有调度表。 或者,代码
table which handles the <code>SomeClass</code> class specially. Alternatively,
 
the code
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第825行: 第564行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>class MyPickler(pickle.Pickler):
+
<syntaxhighlight lang="python3">class MyPickler(pickle.Pickler):
 
     dispatch_table = copyreg.dispatch_table.copy()
 
     dispatch_table = copyreg.dispatch_table.copy()
 
     dispatch_table[SomeClass] = reduce_SomeClass
 
     dispatch_table[SomeClass] = reduce_SomeClass
 
f = io.BytesIO()
 
f = io.BytesIO()
p = MyPickler(f)</pre>
+
p = MyPickler(f)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
does the same, but all instances of <code>MyPickler</code> will by default
+
执行相同的操作,但 <code>MyPickler</code> 的所有实例将默认共享相同的调度表。 使用 [[../copyreg#module-copyreg|copyreg]] 模块的等效代码是
share the same dispatch table. The equivalent code using the
 
[[../copyreg#module-copyreg|<code>copyreg</code>]] module is
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第842行: 第579行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>copyreg.pickle(SomeClass, reduce_SomeClass)
+
<syntaxhighlight lang="python3">copyreg.pickle(SomeClass, reduce_SomeClass)
 
f = io.BytesIO()
 
f = io.BytesIO()
p = pickle.Pickler(f)</pre>
+
p = pickle.Pickler(f)</syntaxhighlight>
  
 
</div>
 
</div>
第854行: 第591行:
  
 
<span id="pickle-state"></span>
 
<span id="pickle-state"></span>
=== Handling Stateful Objects ===
+
=== 处理有状态对象 ===
  
Here's an example that shows how to modify pickling behavior for a class.
+
这是一个示例,展示了如何修改类的酸洗行为。 <code>TextReader</code> 类打开一个文本文件,并在每次调用其 <code>readline()</code> 方法时返回行号和行内容。 如果一个 <code>TextReader</code> 实例被腌制,则所有属性 '''' 文件对象成员被保存。 当实例被 unpickle 时,文件被重新打开,并从最后一个位置继续读取。 <code>__setstate__()</code> <code>__getstate__()</code> 方法用于实现此行为。
The <code>TextReader</code> class opens a text file, and returns the line number and
 
line contents each time its <code>readline()</code> method is called. If a
 
<code>TextReader</code> instance is pickled, all attributes ''except'' the file object
 
member are saved. When the instance is unpickled, the file is reopened, and
 
reading resumes from the last location. The <code>__setstate__()</code> and
 
<code>__getstate__()</code> methods are used to implement this behavior.
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第868行: 第599行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>class TextReader:
+
<syntaxhighlight lang="python3">class TextReader:
     &quot;&quot;&quot;Print and number lines in a text file.&quot;&quot;&quot;
+
     """Print and number lines in a text file."""
  
 
     def __init__(self, filename):
 
     def __init__(self, filename):
第883行: 第614行:
 
         if line.endswith('\n'):
 
         if line.endswith('\n'):
 
             line = line[:-1]
 
             line = line[:-1]
         return &quot;%i: %s&quot; % (self.lineno, line)
+
         return "%i: %s" % (self.lineno, line)
  
 
     def __getstate__(self):
 
     def __getstate__(self):
第903行: 第634行:
 
             file.readline()
 
             file.readline()
 
         # Finally, save the file.
 
         # Finally, save the file.
         self.file = file</pre>
+
         self.file = file</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
A sample usage might be something like this:
+
示例用法可能是这样的:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第914行: 第645行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; reader = TextReader(&quot;hello.txt&quot;)
+
<syntaxhighlight lang="python3">>>> reader = TextReader("hello.txt")
&gt;&gt;&gt; reader.readline()
+
>>> reader.readline()
 
'1: Hello world!'
 
'1: Hello world!'
&gt;&gt;&gt; reader.readline()
+
>>> reader.readline()
 
'2: I am line number two.'
 
'2: I am line number two.'
&gt;&gt;&gt; new_reader = pickle.loads(pickle.dumps(reader))
+
>>> new_reader = pickle.loads(pickle.dumps(reader))
&gt;&gt;&gt; new_reader.readline()
+
>>> new_reader.readline()
'3: Goodbye!'</pre>
+
'3: Goodbye!'</syntaxhighlight>
  
 
</div>
 
</div>
第933行: 第664行:
  
 
<span id="reducer-override"></span>
 
<span id="reducer-override"></span>
== Custom Reduction for Types, Functions, and Other Objects ==
+
== 类型、函数和其他对象的自定义缩减 ==
  
 
<div class="versionadded">
 
<div class="versionadded">
  
<span class="versionmodified added">3.8 新版功能.</span>
+
<span class="versionmodified added">3.8 版中的新功能。</span>
  
  
 
</div>
 
</div>
Sometimes, [[#pickle.Pickler.dispatch_table|<code>dispatch_table</code>]] may not be flexible enough.
+
有时, [[#pickle.Pickler.dispatch_table|dispatch_table]] 可能不够灵活。 特别是我们可能希望根据对象类型以外的其他标准自定义酸洗,或者我们可能希望自定义函数和类的酸洗。
In particular we may want to customize pickling based on another criterion
 
than the object's type, or we may want to customize the pickling of
 
functions and classes.
 
  
For those cases, it is possible to subclass from the [[#pickle.Pickler|<code>Pickler</code>]] class and
+
对于这些情况,可以从 [[#pickle.Pickler|Picker]] 类继承子类并实现 [[#pickle.Pickler.reducer_override|reducer_override()]] 方法。 这个方法可以返回一个任意的归约元组(见 <code>__reduce__()</code>)。 它也可以返回 <code>NotImplemented</code> 以回退到传统行为。
implement a [[#pickle.Pickler.reducer_override|<code>reducer_override()</code>]] method. This method can return an
 
arbitrary reduction tuple (see <code>__reduce__()</code>). It can alternatively return
 
<code>NotImplemented</code> to fallback to the traditional behavior.
 
  
If both the [[#pickle.Pickler.dispatch_table|<code>dispatch_table</code>]] and
+
如果同时定义了 [[#pickle.Pickler.dispatch_table|dispatch_table]] [[#pickle.Pickler.reducer_override|reducer_override()]],那么 [[#pickle.Pickler.reducer_override|reducer_override()]] 方法优先。
[[#pickle.Pickler.reducer_override|<code>reducer_override()</code>]] are defined, then
 
[[#pickle.Pickler.reducer_override|<code>reducer_override()</code>]] method takes priority.
 
  
 
<div class="admonition note">
 
<div class="admonition note">
  
注解
+
笔记
  
For performance reasons, [[#pickle.Pickler.reducer_override|<code>reducer_override()</code>]] may not be
+
出于性能原因,可能不会为以下对象调用 [[#pickle.Pickler.reducer_override|reducer_override()]]<code>None</code><code>True</code><code>False</code> [[../functions#int|的确切实例int]], [[../functions#float|float]], [[../stdtypes#bytes|bytes]], [[../stdtypes#str|str]], [[../stdtypes#dict|dict]], [[../stdtypes#set|set]], X257X][[../stdtypes#list|列表]] [[../stdtypes#tuple|元组]]
called for the following objects: <code>None</code>, <code>True</code>, <code>False</code>, and
 
exact instances of [[../functions#int|<code>int</code>]], [[../functions#float|<code>float</code>]], [[../stdtypes#bytes|<code>bytes</code>]],
 
[[../stdtypes#str|<code>str</code>]], [[../stdtypes#dict|<code>dict</code>]], [[../stdtypes#set|<code>set</code>]], [[../stdtypes#frozenset|<code>frozenset</code>]], [[../stdtypes#list|<code>list</code>]]
 
and [[../stdtypes#tuple|<code>tuple</code>]].
 
  
  
 
</div>
 
</div>
Here is a simple example where we allow pickling and reconstructing
+
这是一个简单的例子,我们允许酸洗和重建给定的类:
a given class:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第974行: 第692行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>import io
+
<syntaxhighlight lang="python3">import io
 
import pickle
 
import pickle
  
第982行: 第700行:
 
class MyPickler(pickle.Pickler):
 
class MyPickler(pickle.Pickler):
 
     def reducer_override(self, obj):
 
     def reducer_override(self, obj):
         &quot;&quot;&quot;Custom reducer for MyClass.&quot;&quot;&quot;
+
         """Custom reducer for MyClass."""
         if getattr(obj, &quot;__name__&quot;, None) == &quot;MyClass&quot;:
+
         if getattr(obj, "__name__", None) == "MyClass":
 
             return type, (obj.__name__, obj.__bases__,
 
             return type, (obj.__name__, obj.__bases__,
 
                           {'my_attribute': obj.my_attribute})
 
                           {'my_attribute': obj.my_attribute})
第999行: 第717行:
  
 
assert isinstance(unpickled_class, type)
 
assert isinstance(unpickled_class, type)
assert unpickled_class.__name__ == &quot;MyClass&quot;
+
assert unpickled_class.__name__ == "MyClass"
assert unpickled_class.my_attribute == 1</pre>
+
assert unpickled_class.my_attribute == 1</syntaxhighlight>
  
 
</div>
 
</div>
第1,010行: 第728行:
  
 
<span id="pickle-oob"></span>
 
<span id="pickle-oob"></span>
== Out-of-band Buffers ==
+
== 带外缓冲器 ==
  
 
<div class="versionadded">
 
<div class="versionadded">
  
<span class="versionmodified added">3.8 新版功能.</span>
+
<span class="versionmodified added">3.8 版中的新功能。</span>
  
  
 
</div>
 
</div>
In some contexts, the [[#module-pickle|<code>pickle</code>]] module is used to transfer massive amounts
+
在某些情况下,[[#module-pickle|pickle]] 模块用于传输大量数据。 因此,尽量减少内存副本的数量以保持性能和资源消耗可能很重要。 但是,[[#module-pickle|pickle]] 模块的正常操作,因为它将对象的图形结构转换为字节的顺序流,本质上涉及将数据复制到pickle 流或从pickle 流复制数据。
of data. Therefore, it can be important to minimize the number of memory
 
copies, to preserve performance and resource consumption. However, normal
 
operation of the [[#module-pickle|<code>pickle</code>]] module, as it transforms a graph-like structure
 
of objects into a sequential stream of bytes, intrinsically involves copying
 
data to and from the pickle stream.
 
  
This constraint can be eschewed if both the ''provider'' (the implementation
+
如果 ''provider''(要传输的对象类型的实现)和 ''consumer''(通信系统的实现)都支持带外pickle 协议 5 及更高版本提供的传输设施。
of the object types to be transferred) and the ''consumer'' (the implementation
 
of the communications system) support the out-of-band transfer facilities
 
provided by pickle protocol 5 and higher.
 
  
 
<div id="provider-api" class="section">
 
<div id="provider-api" class="section">
  
=== Provider API ===
+
=== 提供者 API ===
  
The large data objects to be pickled must implement a <code>__reduce_ex__()</code>
+
要被pickle的大数据对象必须实现一个专用于协议5及更高版本的<code>__reduce_ex__()</code>方法,该方法返回一个[[#pickle.PickleBuffer|PickleBuffer]]实例(而不是例如 一个 [[../stdtypes#bytes|bytes]] 对象)用于任何大数据。
method specialized for protocol 5 and higher, which returns a
 
[[#pickle.PickleBuffer|<code>PickleBuffer</code>]] instance (instead of e.g. a [[../stdtypes#bytes|<code>bytes</code>]] object)
 
for any large data.
 
  
A [[#pickle.PickleBuffer|<code>PickleBuffer</code>]] object ''signals'' that the underlying buffer is
+
[[#pickle.PickleBuffer|PickleBuffer]] 对象 ''发出信号'' 表明底层缓冲区有资格进行带外数据传输。 这些对象与 [[#module-pickle|pickle]] 模块的正常使用保持兼容。 但是,消费者也可以选择告诉 [[#module-pickle|pickle]] 他们将自己处理这些缓冲区。
eligible for out-of-band data transfer. Those objects remain compatible
 
with normal usage of the [[#module-pickle|<code>pickle</code>]] module. However, consumers can also
 
opt-in to tell [[#module-pickle|<code>pickle</code>]] that they will handle those buffers by
 
themselves.
 
  
  
第1,049行: 第752行:
 
<div id="consumer-api" class="section">
 
<div id="consumer-api" class="section">
  
=== Consumer API ===
+
=== 消费者API ===
  
A communications system can enable custom handling of the [[#pickle.PickleBuffer|<code>PickleBuffer</code>]]
+
通信系统可以启用对序列化对象图时生成的 [[#pickle.PickleBuffer|PickleBuffer]] 对象的自定义处理。
objects generated when serializing an object graph.
 
  
On the sending side, it needs to pass a ''buffer_callback'' argument to
+
在发送端,它需要将 ''buffer_callback'' 参数传递给 [[#pickle.Pickler|Pickler]](或 [[#pickle.dump|dump()]] [[#pickle.dumps|dumps()]] 函数),它将在酸洗对象图时生成的每个 [[#pickle.PickleBuffer|PickleBuffer]] 被调用。 ''buffer_callback'' 累积的缓冲区不会看到它们的数据复制到pickle 流中,只会插入一个廉价的标记。
[[#pickle.Pickler|<code>Pickler</code>]] (or to the [[#pickle.dump|<code>dump()</code>]] or [[#pickle.dumps|<code>dumps()</code>]] function), which
 
will be called with each [[#pickle.PickleBuffer|<code>PickleBuffer</code>]] generated while pickling
 
the object graph. Buffers accumulated by the ''buffer_callback'' will not
 
see their data copied into the pickle stream, only a cheap marker will be
 
inserted.
 
  
On the receiving side, it needs to pass a ''buffers'' argument to
+
在接收端,它需要将 ''buffers'' 参数传递给 [[#pickle.Unpickler|Unpickler]](或 [[#pickle.load|load()]] [[#pickle.loads|loads()]] 函数),这是传递给 ''buffer_callback'' 的缓冲区的可迭代对象。 该可迭代对象应该按照传递给 ''buffer_callback'' 的相同顺序生成缓冲区。 这些缓冲区将提供对象的重构器所期望的数据,这些对象的酸洗产生了原始的 [[#pickle.PickleBuffer|PickleBuffer]] 对象。
[[#pickle.Unpickler|<code>Unpickler</code>]] (or to the [[#pickle.load|<code>load()</code>]] or [[#pickle.loads|<code>loads()</code>]] function),
 
which is an iterable of the buffers which were passed to ''buffer_callback''.
 
That iterable should produce buffers in the same order as they were passed
 
to ''buffer_callback''. Those buffers will provide the data expected by the
 
reconstructors of the objects whose pickling produced the original
 
[[#pickle.PickleBuffer|<code>PickleBuffer</code>]] objects.
 
  
Between the sending side and the receiving side, the communications system
+
在发送端和接收端之间,通信系统可以自由地实现自己的带外缓冲区传输机制。 潜在的优化包括使用共享内存或依赖于数据类型的压缩。
is free to implement its own transfer mechanism for out-of-band buffers.
 
Potential optimizations include the use of shared memory or datatype-dependent
 
compression.
 
  
  
第1,078行: 第766行:
 
<div id="example" class="section">
 
<div id="example" class="section">
  
=== Example ===
+
=== 例子 ===
  
Here is a trivial example where we implement a [[../stdtypes#bytearray|<code>bytearray</code>]] subclass
+
这是一个简单的例子,我们实现了一个能够参与带外缓冲区酸洗的 [[../stdtypes#bytearray|bytearray]] 子类:
able to participate in out-of-band buffer pickling:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,087行: 第774行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>class ZeroCopyByteArray(bytearray):
+
<syntaxhighlight lang="python3">class ZeroCopyByteArray(bytearray):
  
 
     def __reduce_ex__(self, protocol):
 
     def __reduce_ex__(self, protocol):
         if protocol &gt;= 5:
+
         if protocol >= 5:
 
             return type(self)._reconstruct, (PickleBuffer(self),), None
 
             return type(self)._reconstruct, (PickleBuffer(self),), None
 
         else:
 
         else:
             # PickleBuffer is forbidden with pickle protocols &lt;= 4.
+
             # PickleBuffer is forbidden with pickle protocols <= 4.
 
             return type(self)._reconstruct, (bytearray(self),)
 
             return type(self)._reconstruct, (bytearray(self),)
  
第1,106行: 第793行:
 
                 return obj
 
                 return obj
 
             else:
 
             else:
                 return cls(obj)</pre>
+
                 return cls(obj)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The reconstructor (the <code>_reconstruct</code> class method) returns the buffer's
+
重构器(<code>_reconstruct</code> 类方法)返回缓冲区的提供对象,如果它具有正确的类型。 这是在这个玩具示例上模拟零复制行为的简单方法。
providing object if it has the right type. This is an easy way to simulate
 
zero-copy behaviour on this toy example.
 
  
On the consumer side, we can pickle those objects the usual way, which
+
在消费者方面,我们可以用通常的方式腌制这些对象,反序列化时会给我们一个原始对象的副本:
when unserialized will give us a copy of the original object:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,122行: 第806行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>b = ZeroCopyByteArray(b&quot;abc&quot;)
+
<syntaxhighlight lang="python3">b = ZeroCopyByteArray(b"abc")
 
data = pickle.dumps(b, protocol=5)
 
data = pickle.dumps(b, protocol=5)
 
new_b = pickle.loads(data)
 
new_b = pickle.loads(data)
 
print(b == new_b)  # True
 
print(b == new_b)  # True
print(b is new_b)  # False: a copy was made</pre>
+
print(b is new_b)  # False: a copy was made</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
But if we pass a ''buffer_callback'' and then give back the accumulated
+
但是如果我们传递一个 ''buffer_callback'' 然后在反序列化时返回累积的缓冲区,我们就可以取回原始对象:
buffers when unserializing, we are able to get back the original object:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,138行: 第821行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>b = ZeroCopyByteArray(b&quot;abc&quot;)
+
<syntaxhighlight lang="python3">b = ZeroCopyByteArray(b"abc")
 
buffers = []
 
buffers = []
 
data = pickle.dumps(b, protocol=5, buffer_callback=buffers.append)
 
data = pickle.dumps(b, protocol=5, buffer_callback=buffers.append)
 
new_b = pickle.loads(data, buffers=buffers)
 
new_b = pickle.loads(data, buffers=buffers)
 
print(b == new_b)  # True
 
print(b == new_b)  # True
print(b is new_b)  # True: no copy was made</pre>
+
print(b is new_b)  # True: no copy was made</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
This example is limited by the fact that [[../stdtypes#bytearray|<code>bytearray</code>]] allocates its
+
此示例受到 [[../stdtypes#bytearray|bytearray]] 分配自己的内存这一事实的限制:您不能创建由另一个对象的内存支持的 [[../stdtypes#bytearray|bytearray]] 实例。 但是,第三方数据类型(例如 NumPy 数组)没有此限制,并且在不同的进程或系统之间传输时允许使用零副本酸洗(或制作尽可能少的副本)。
own memory: you cannot create a [[../stdtypes#bytearray|<code>bytearray</code>]] instance that is backed
 
by another object's memory. However, third-party datatypes such as NumPy
 
arrays do not have this limitation, and allow use of zero-copy pickling
 
(or making as few copies as possible) when transferring between distinct
 
processes or systems.
 
  
 
<div class="admonition seealso">
 
<div class="admonition seealso">
  
参见
+
也可以看看
  
<span id="index-8" class="target"></span>[https://www.python.org/dev/peps/pep-0574 '''PEP 574'''] -- Pickle protocol 5 with out-of-band data
+
<span id="index-8" class="target"></span>[https://www.python.org/dev/peps/pep-0574 PEP 574] – 带外数据的 Pickle 协议 5
  
  
第1,170行: 第848行:
  
 
<span id="pickle-restrict"></span>
 
<span id="pickle-restrict"></span>
== Restricting Globals ==
+
== 限制全局变量 ==
  
By default, unpickling will import any class or function that it finds in the
+
默认情况下,unpickling 将导入它在 pickle 数据中找到的任何类或函数。 对于许多应用程序,这种行为是不可接受的,因为它允许 unpickler 导入和调用任意代码。 只需考虑加载时这个手工制作的pickle数据流的作用:
pickle data. For many applications, this behaviour is unacceptable as it
 
permits the unpickler to import and invoke arbitrary code. Just consider what
 
this hand-crafted pickle data stream does when loaded:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,181行: 第856行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; import pickle
+
<syntaxhighlight lang="python3">>>> import pickle
&gt;&gt;&gt; pickle.loads(b&quot;cos\nsystem\n(S'echo hello world'\ntR.&quot;)
+
>>> pickle.loads(b"cos\nsystem\n(S'echo hello world'\ntR.")
 
hello world
 
hello world
0</pre>
+
0</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
In this example, the unpickler imports the [[../os#os|<code>os.system()</code>]] function and then
+
在这个例子中,unpickler 导入 [[../os#os|os.system()]] 函数,然后应用字符串参数“echo hello world”。 尽管此示例无害,但不难想象可能会损坏您的系统的示例。
apply the string argument &quot;echo hello world&quot;. Although this example is
 
inoffensive, it is not difficult to imagine one that could damage your system.
 
  
For this reason, you may want to control what gets unpickled by customizing
+
出于这个原因,您可能希望通过自定义 [[#pickle.Unpickler.find_class|Unpickler.find_class()]] 来控制什么被取消。 与其名称所暗示的不同,只要请求全局(即类或函数),就会调用 [[#pickle.Unpickler.find_class|Unpickler.find_class()]]。 因此,可以完全禁止全局变量或将它们限制为安全子集。
[[#pickle.Unpickler.find_class|<code>Unpickler.find_class()</code>]]. Unlike its name suggests,
 
[[#pickle.Unpickler.find_class|<code>Unpickler.find_class()</code>]] is called whenever a global (i.e., a class or
 
a function) is requested. Thus it is possible to either completely forbid
 
globals or restrict them to a safe subset.
 
  
Here is an example of an unpickler allowing only few safe classes from the
+
下面是一个 unpickler 的例子,它只允许加载 [[../builtins#module-builtins|builtins]] 模块中的几个安全类:
[[../builtins#module-builtins|<code>builtins</code>]] module to be loaded:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,206行: 第874行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>import builtins
+
<syntaxhighlight lang="python3">import builtins
 
import io
 
import io
 
import pickle
 
import pickle
第1,222行: 第890行:
 
     def find_class(self, module, name):
 
     def find_class(self, module, name):
 
         # Only allow safe classes from builtins.
 
         # Only allow safe classes from builtins.
         if module == &quot;builtins&quot; and name in safe_builtins:
+
         if module == "builtins" and name in safe_builtins:
 
             return getattr(builtins, name)
 
             return getattr(builtins, name)
 
         # Forbid everything else.
 
         # Forbid everything else.
         raise pickle.UnpicklingError(&quot;global '%s.%s' is forbidden&quot; %
+
         raise pickle.UnpicklingError("global '%s.%s' is forbidden" %
 
                                     (module, name))
 
                                     (module, name))
  
 
def restricted_loads(s):
 
def restricted_loads(s):
     &quot;&quot;&quot;Helper function analogous to pickle.loads().&quot;&quot;&quot;
+
     """Helper function analogous to pickle.loads()."""
     return RestrictedUnpickler(io.BytesIO(s)).load()</pre>
+
     return RestrictedUnpickler(io.BytesIO(s)).load()</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
A sample usage of our unpickler working has intended:
+
我们的 unpickler 工作的示例用法旨在:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,241行: 第909行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; restricted_loads(pickle.dumps([1, 2, range(15)]))
+
<syntaxhighlight lang="python3">>>> restricted_loads(pickle.dumps([1, 2, range(15)]))
 
[1, 2, range(0, 15)]
 
[1, 2, range(0, 15)]
&gt;&gt;&gt; restricted_loads(b&quot;cos\nsystem\n(S'echo hello world'\ntR.&quot;)
+
>>> restricted_loads(b"cos\nsystem\n(S'echo hello world'\ntR.")
 
Traceback (most recent call last):
 
Traceback (most recent call last):
 
   ...
 
   ...
 
pickle.UnpicklingError: global 'os.system' is forbidden
 
pickle.UnpicklingError: global 'os.system' is forbidden
&gt;&gt;&gt; restricted_loads(b'cbuiltins\neval\n'
+
>>> restricted_loads(b'cbuiltins\neval\n'
...                  b'(S\'getattr(__import__(&quot;os&quot;), &quot;system&quot;)'
+
...                  b'(S\'getattr(__import__("os"), "system")'
...                  b'(&quot;echo hello world&quot;)\'\ntR.')
+
...                  b'("echo hello world")\'\ntR.')
 
Traceback (most recent call last):
 
Traceback (most recent call last):
 
   ...
 
   ...
pickle.UnpicklingError: global 'builtins.eval' is forbidden</pre>
+
pickle.UnpicklingError: global 'builtins.eval' is forbidden</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
As our examples shows, you have to be careful with what you allow to be
+
正如我们的例子所示,你必须小心你允许去腌制的东西。 因此,如果担心安全性,您可能需要考虑替代方案,例如 [[../xmlrpc.client#module-xmlrpc|xmlrpc.client]] 中的编组 API 或第三方解决方案。
unpickled. Therefore if security is a concern, you may want to consider
 
alternatives such as the marshalling API in [[../xmlrpc.client#module-xmlrpc|<code>xmlrpc.client</code>]] or
 
third-party solutions.
 
  
  
第1,266行: 第931行:
 
<div id="performance" class="section">
 
<div id="performance" class="section">
  
== Performance ==
+
== 表现 ==
  
Recent versions of the pickle protocol (from protocol 2 and upwards) feature
+
pickle 协议的最新版本(从协议 2 开始)为几个常见功能和内置类型提供了高效的二进制编码。 此外,[[#module-pickle|pickle]] 模块有一个用 C 编写的透明优化器。
efficient binary encodings for several common features and built-in types.
 
Also, the [[#module-pickle|<code>pickle</code>]] module has a transparent optimizer written in C.
 
  
  
第1,277行: 第940行:
  
 
<span id="pickle-example"></span>
 
<span id="pickle-example"></span>
== Examples ==
+
== 例子 ==
  
For the simplest code, use the [[#pickle.dump|<code>dump()</code>]] and [[#pickle.load|<code>load()</code>]] functions.
+
对于最简单的代码,使用 [[#pickle.dump|dump()]] [[#pickle.load|load()]] 函数。
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,285行: 第948行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>import pickle
+
<syntaxhighlight lang="python3">import pickle
  
 
# An arbitrary collection of objects supported by pickle.
 
# An arbitrary collection of objects supported by pickle.
 
data = {
 
data = {
 
     'a': [1, 2.0, 3, 4+6j],
 
     'a': [1, 2.0, 3, 4+6j],
     'b': (&quot;character string&quot;, b&quot;byte string&quot;),
+
     'b': ("character string", b"byte string"),
 
     'c': {None, True, False}
 
     'c': {None, True, False}
 
}
 
}
第1,296行: 第959行:
 
with open('data.pickle', 'wb') as f:
 
with open('data.pickle', 'wb') as f:
 
     # Pickle the 'data' dictionary using the highest protocol available.
 
     # Pickle the 'data' dictionary using the highest protocol available.
     pickle.dump(data, f, pickle.HIGHEST_PROTOCOL)</pre>
+
     pickle.dump(data, f, pickle.HIGHEST_PROTOCOL)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The following example reads the resulting pickled data.
+
以下示例读取生成的腌制数据。
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,307行: 第970行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>import pickle
+
<syntaxhighlight lang="python3">import pickle
  
 
with open('data.pickle', 'rb') as f:
 
with open('data.pickle', 'rb') as f:
 
     # The protocol version used is detected automatically, so we do not
 
     # The protocol version used is detected automatically, so we do not
 
     # have to specify it.
 
     # have to specify it.
     data = pickle.load(f)</pre>
+
     data = pickle.load(f)</syntaxhighlight>
  
 
</div>
 
</div>
第1,319行: 第982行:
 
<div class="admonition seealso">
 
<div class="admonition seealso">
  
参见
+
也可以看看
  
; Module [[../copyreg#module-copyreg|<code>copyreg</code>]]
+
; 模块 [[../copyreg#module-copyreg|copyreg]]
: Pickle interface constructor registration for extension types.
+
: 扩展类型的 Pickle 接口构造函数注册。
; Module [[../pickletools#module-pickletools|<code>pickletools</code>]]
+
; 模块 [[../pickletools#module-pickletools|pickletools]]
: Tools for working with and analyzing pickled data.
+
: 用于处理和分析腌制数据的工具。
; Module [[../shelve#module-shelve|<code>shelve</code>]]
+
; 模块 [[../shelve#module-shelve|搁架]]
: Indexed databases of objects; uses [[#module-pickle|<code>pickle</code>]].
+
: 对象的索引数据库; 使用 [[#module-pickle|pickle]]
; Module [[../copy#module-copy|<code>copy</code>]]
+
; 模块[[../copy#module-copy|复制]]
: Shallow and deep object copying.
+
: 浅层和深层对象复制。
; Module [[../marshal#module-marshal|<code>marshal</code>]]
+
; 模块[[../marshal#module-marshal|元帅]]
: High-performance serialization of built-in types.
+
: 内置类型的高性能序列化。
  
  
 
</div>
 
</div>
Footnotes
+
脚注
 +
 
 +
; <span class="brackets">[[#id3|1]]</span>
 +
: 不要将其与 [[../marshal#module-marshal|marshal]] 模块混淆
 +
; <span class="brackets">[[#id5|2]]</span>
 +
: 这就是为什么 [[../../reference/expressions#lambda|lambda]] 函数不能被腌制的原因:所有 <code>lambda</code> 函数共享同一个名称:<code>&lt;lambda&gt;</code>。
 +
; <span class="brackets">[[#id6|3]]</span>
 +
: 引发的异常可能是 [[../exceptions#ImportError|ImportError]] 或 [[../exceptions#AttributeError|AttributeError]],但也可能是别的东西。
 +
; <span class="brackets">[[#id7|4]]</span>
 +
: [[../copy#module-copy|copy]] 模块使用这个协议进行浅拷贝和深拷贝操作。
 +
; <span class="brackets">[[#id8|5]]</span>
 +
: 对字母数字字符的限制是因为协议 0 中的持久 ID 由换行符分隔。 因此,如果持久 ID 中出现任何类型的换行符,则生成的 pickle 将变得不可读。
  
; <span class="brackets">[[#id1|1]]</span>
 
: Don't confuse this with the [[../marshal#module-marshal|<code>marshal</code>]] module
 
; <span class="brackets">[[#id3|2]]</span>
 
: This is why [[../../reference/expressions#lambda|<code>lambda</code>]] functions cannot be pickled: all <code>lambda</code> functions share the same name: <code>&lt;lambda&gt;</code>.
 
; <span class="brackets">[[#id4|3]]</span>
 
: The exception raised will likely be an [[../exceptions#ImportError|<code>ImportError</code>]] or an [[../exceptions#AttributeError|<code>AttributeError</code>]] but it could be something else.
 
; <span class="brackets">[[#id5|4]]</span>
 
: The [[../copy#module-copy|<code>copy</code>]] module uses this protocol for shallow and deep copying operations.
 
; <span class="brackets">[[#id6|5]]</span>
 
: The limitation on alphanumeric characters is due to the fact the persistent IDs, in protocol 0, are delimited by the newline character. Therefore if any kind of newline characters occurs in persistent IDs, the resulting pickle will become unreadable.
 
  
 +
</div>
  
 
</div>
 
</div>
 +
<div class="clearer">
 +
 +
  
 
</div>
 
</div>
  
[[Category:Python 3.9 中文文档]]
+
[[Category:Python 3.9 文档]]

2021年10月31日 (日) 04:53的最新版本

pickle — Python 对象序列化

源代码: :source:`Lib/pickle.py`



pickle 模块实现了用于序列化和反序列化 Python 对象结构的二进制协议。 “Pickling” 是将 Python 对象层次结构转换为字节流的过程,而 “unpickling” 是逆操作,由此字节流(来自 二进制filebytes-like object) 被转换回对象层次结构。 酸洗(和取消酸洗)也称为“序列化”、“编组”、1 或“扁平化”; 然而,为了避免混淆,这里使用的术语是“酸洗”和“解酸”。

警告

pickle 模块 不安全 。 只解压您信任的数据。

有可能构建恶意pickle数据,在unpickling期间执行任意代码。 永远不要解开可能来自不受信任的来源或可能被篡改的数据。

如果您需要确保数据未被篡改,请考虑使用 hmac 对数据进行签名。

如果您正在处理不受信任的数据,更安全的序列化格式(例如 json)可能更合适。 参见 与 json 的比较。


与其他 Python 模块的关系

与marshal的比较

Python 有一个更原始的序列化模块,称为 marshal,但总的来说,pickle 应该始终是序列化 Python 对象的首选方式。 marshal 的存在主要是为了支持 Python 的 .pyc 文件。

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

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

    这对递归对象和对象共享都有影响。 递归对象是包含对自身的引用的对象。 这些不是由 marshal 处理的,实际上,尝试 marshal 递归对象会使您的 Python 解释器崩溃。 当在被序列化的对象层次结构中的不同位置对同一对象有多个引用时,就会发生对象共享。 pickle 仅存储此类对象一次,并确保所有其他引用都指向主副本。 共享对象保持共享状态,这对于可变对象非常重要。

  • marshal 不能用于序列化用户定义的类及其实例。 pickle 可以透明地保存和恢复类实例,但是类定义必须是可导入的,并且与存储对象时存在于同一模块中。

  • marshal 序列化格式不能保证跨 Python 版本可移植。 因为 Python 的主要工作是支持 .pyc 文件,所以 Python 实现者保留在需要时以非向后兼容的方式更改序列化格式的权利。 pickle 序列化格式保证在 Python 版本之间向后兼容,前提是选择了兼容的 pickle 协议,并且如果您的数据跨越了那个独特的突破性更改语言,pickle 和 unpickling 代码处理 Python 2 到 Python 3 的类型差异边界。


与json的比较

pickle 协议和 JSON(JavaScript Object Notation) 之间存在根本区别:

  • JSON 是一种文本序列化格式(它输出 unicode 文本,尽管大多数时候它会被编码为 utf-8),而 pickle 是一种二进制序列化格式;
  • JSON 是人类可读的,而 pickle 不是;
  • JSON 是可互操作的,并且在 Python 生态系统之外广泛使用,而 pickle 是特定于 Python 的;
  • 默认情况下,JSON 只能表示 Python 内置类型的一个子集,而没有自定义类; pickle 可以表示非常多的 Python 类型(其中许多是自动的,通过巧妙地使用 Python 的自省设施;复杂的情况可以通过实现 特定对象 API 来解决);
  • 与 pickle 不同,反序列化不受信任的 JSON 本身不会产生任意代码执行漏洞。

也可以看看

json 模块:一个允许 JSON 序列化和反序列化的标准库模块。


数据流格式

pickle 使用的数据格式是 Python 特定的。 这样做的好处是不受外部标准的限制,例如 JSON 或 XDR(不能代表指针共享); 然而,这意味着非 Python 程序可能无法重建腌制的 Python 对象。

默认情况下,pickle 数据格式使用相对紧凑的二进制表示。 如果您需要最佳尺寸特征,您可以有效地 压缩 腌制数据。

模块 pickletools 包含用于分析由 pickle 生成的数据流的工具。 pickletools 源代码对pickle 协议使用的操作码有大量注释。

目前有 6 种不同的协议可用于酸洗。 使用的协议越高,读取生成的泡菜所需的 Python 版本就越新。

  • 协议版本 0 是原始的“人类可读”协议,向后兼容早期版本的 Python。
  • 协议版本 1 是一种旧的二进制格式,它也与早期版本的 Python 兼容。
  • 协议版本 2 是在 Python 2.3 中引入的。 它为 新式类 提供了更有效的酸洗。 有关协议 2 带来的改进的信息,请参阅 PEP 307
  • Python 3.0 中添加了协议版本 3。 它明确支持 bytes 对象,并且不能被 Python 2.x 解压。 这是 Python 3.0-3.7 中的默认协议。
  • Python 3.4 中添加了协议版本 4。 它增加了对超大对象的支持,酸洗更多种类的对象,以及一些数据格式优化。 它是从 Python 3.8 开始的默认协议。 有关协议 4 带来的改进的信息,请参阅 PEP 3154
  • Python 3.8 中添加了协议版本 5。 它增加了对带外数据的支持和对带内数据的加速。 有关协议 5 带来的改进的信息,请参阅 PEP 574

笔记

序列化是一个比持久化更原始的概念; pickle虽然读写文件对象,但它没有处理命名持久对象的问题,也没有处理持久对象的并发访问(甚至更复杂)的问题。 pickle 模块可以将复杂对象转换为字节流,也可以将字节流转换为具有相同内部结构的对象。 也许对这些字节流做的最明显的事情是将它们写入文件,但也可以通过网络发送它们或将它们存储在数据库中。 shelve 模块提供了一个简单的接口来pickle 和unpickle DBM 样式数据库文件上的对象。


模块接口

要序列化对象层次结构,只需调用 dumps() 函数。 类似地,要反序列化数据流,您可以调用 loads() 函数。 但是,如果您想对序列化和反序列化进行更多控制,则可以分别创建 PicklerUnpickler 对象。

pickle 模块提供以下常量:

pickle.HIGHEST_PROTOCOL
一个整数,可用的最高 协议版本 。 该值可以作为 protocol 值传递给函数 dump()dumps() 以及 Picker 构造函数。
pickle.DEFAULT_PROTOCOL

一个整数,默认 协议版本 用于酸洗。 可能小于 HIGHEST_PROTOCOL。 目前默认的协议是 4,最初是在 Python 3.4 中引入的,与之前的版本不兼容。

3.0版本变化:默认协议为3。

3.8版本变化:默认协议为4。

pickle模块提供了以下功能,让pickle过程更加方便:

pickle.dump(obj, file, protocol=None, *, fix_imports=True, buffer_callback=None)

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

参数 fileprotocolfix_importsbuffer_callbackPickler 构造函数中的含义相同。

3.8 版更改: 添加了 buffer_callback 参数。

pickle.dumps(obj, protocol=None, *, fix_imports=True, buffer_callback=None)

将对象 obj 的腌制表示返回为 bytes 对象,而不是将其写入文件。

参数 protocolfix_importsbuffer_callbackPicker 构造函数中的含义相同。

3.8 版更改: 添加了 buffer_callback 参数。

pickle.load(file, *, fix_imports=True, encoding='ASCII', errors='strict', buffers=None)

从打开的 文件对象 文件 中读取对象的酸洗表示,并返回其中指定的重组对象层次结构。 这相当于 Unpickler(file).load()

pickle 的协议版本是自动检测的,因此不需要协议参数。 超过对象的pickle 表示的字节将被忽略。

参数 filefix_importsencodingerrorsstrictbuffersUnpickler 构造函数中的含义相同。

3.8 版更改: 添加了 buffers 参数。

pickle.loads(data, /, *, fix_imports=True, encoding='ASCII', errors='strict', buffers=None)

返回对象的pickle 表示data 的重构对象层次结构。 data 必须是一个 bytes-like object

pickle 的协议版本是自动检测的,因此不需要协议参数。 超过对象的pickle 表示的字节将被忽略。

参数 filefix_importsencodingerrorsstrictbuffersUnpickler 构造函数中的含义相同。

3.8 版更改: 添加了 buffers 参数。

pickle 模块定义了三个异常:

exception pickle.PickleError
其他酸洗异常的公共基类。 它继承了 异常
exception pickle.PicklingError

Pickler 遇到不可拾取的对象时引发错误。 它继承了 PickleError

请参阅可以腌制和不腌制的物品?了解可以腌制的物品种类。

exception pickle.UnpicklingError

当解压对象出现问题时引发错误,例如数据损坏或安全违规。 它继承了 PickleError

请注意,在 unpickling 期间也可能引发其他异常,包括(但不一定限于)AttributeError、EOFError、ImportError 和 IndexError。

pickle 模块导出三个类,PickleUnpicklerPickleBuffer

class pickle.Pickler(file, protocol=None, *, fix_imports=True, buffer_callback=None)

这需要一个二进制文件来编写pickle数据流。

可选的 protocol 参数,一个整数,告诉pickler 使用给定的协议; 支持的协议是 0 到 HIGHEST_PROTOCOL。 如果未指定,则默认值为 DEFAULT_PROTOCOL。 如果指定了负数,则选择 HIGHEST_PROTOCOL

file 参数必须具有接受单个字节参数的 write() 方法。 因此,它可以是为二进制写入而打开的磁盘文件、io.BytesIO 实例或任何其他符合此接口的自定义对象。

如果 fix_imports 为 true 且 protocol 小于 3,pickle 将尝试将新的 Python 3 名称映射到 Python 2 中使用的旧模块名称,以便pickle 数据流用 Python 2 可读。

如果 buffer_callback 为 None(默认值),则缓冲区视图将序列化为 file 作为 pickle 流的一部分。

如果 buffer_callback 不是 None,则可以使用缓冲区视图调用任意次数。 如果回调返回 false 值(例如 None),则给定的缓冲区为 带外 ; 否则缓冲区在带内序列化,即 泡菜流里面。

如果 buffer_callback 不是 None 并且 protocol 是 None 或小于 5,则会出错。

3.8 版更改: 添加了 buffer_callback 参数。

dump(obj)

obj 的腌制表示写入构造函数中给出的打开文件对象。

persistent_id(obj)

默认什么都不做。 它存在以便子类可以覆盖它。

如果 persistent_id() 返回 Noneobj 像往常一样被腌制。 任何其他值都会导致 Pickler 将返回值作为 obj 的持久 ID 发出。 这个持久ID的含义应该由Unpickler.persistent_load()定义。 请注意, persistent_id() 返回的值本身不能具有持久 ID。

有关详细信息和使用示例,请参阅 外部对象持久性

dispatch_table

Pickler 对象的调度表是 归约函数 的注册表,可以使用 copyreg.pickle() 声明。 它是一个映射,其键是类,值是归约函数。 归约函数采用关联类的单个参数,并且应符合与 __reduce__() 方法相同的接口。

默认情况下,pickler 对象将没有 dispatch_table 属性,而是使用由 copyreg 模块管理的全局调度表。 但是,要为特定的pickler 对象自定义酸洗,可以将 dispatch_table 属性设置为类似 dict 的对象。 或者,如果 Pickler 的子类具有 dispatch_table 属性,那么这将用作该类实例的默认调度表。

有关用法示例,请参阅 调度表

3.3 版中的新功能。

reducer_override(self, obj)

可以在 Picker 子类中定义的特殊减速器。 此方法优先于 dispatch_table 中的任何减速器。 它应该符合与 __reduce__() 方法相同的接口,并且可以选择返回 NotImplemented 以回退 dispatch_table 注册的减速器以腌制 obj

有关详细示例,请参阅 类型、函数和其他对象的自定义缩减

3.8 版中的新功能。

fast

已弃用。 如果设置为真值,则启用快速模式。 快速模式禁用备忘录的使用,因此通过不生成多余的 PUT 操作码来加速酸洗过程。 它不应该与自引用对象一起使用,否则会导致 Picker 无限递归。

如果您需要更紧凑的泡菜,请使用 pickletools.optimize()

class pickle.Unpickler(file, *, fix_imports=True, encoding='ASCII', errors='strict', buffers=None)

这需要一个二进制文件来读取泡菜数据流。

pickle 的协议版本是自动检测的,因此不需要协议参数。

参数 file 必须有三个方法,一个采用整数参数的 read() 方法,一个采用缓冲区参数的 readinto() 方法和一个不需要参数的 readline() 方法,如 [ X211X]io.BufferedIOBase 接口。 因此,file 可以是为二进制读取而打开的磁盘文件、io.BytesIO 对象或任何其他符合此接口的自定义对象。

可选参数 fix_importsencodingerrors 用于控制对 Python 2 生成的 pickle 流的兼容性支持。 如果 fix_imports 为真,pickle 将尝试将旧的 Python 2 名称映射到 Python 3 中使用的新名称。 encodingerrors 告诉 pickle 如何解码 Python 2 腌制的 8 位字符串实例; 这些分别默认为 'ASCII' 和 'strict'。 encoding 可以是 'bytes' 来读取这些 8 位字符串实例作为字节对象。 需要使用 encoding='latin1' 来取消 NumPy 数组和 datetimedatetime 由 Python 2 酸洗的实例。

如果 buffers 为 None(默认值),则反序列化所需的所有数据都必须包含在 pickle 流中。 这意味着 buffer_callback 参数在 Pickler 被实例化时(或当 dump()dumps() 被调用时)为 None .

如果 buffers 不是 None,则它应该是启用缓冲区的对象的迭代,每次 pickle 流引用 带外 缓冲区视图时都会消耗该对象。 这些缓冲区是为了给 Pickler 对象的 buffer_callback 提供的。

3.8 版更改: 添加了 buffers 参数。

load()

从构造函数中给出的打开文件对象中读取对象的腌制表示,并返回其中指定的重构对象层次结构。 超过对象的pickle 表示的字节将被忽略。

persistent_load(pid)

默认情况下引发 UnpicklingError

如果已定义,persistent_load() 应返回由持久 ID pid 指定的对象。 如果遇到无效的持久 ID,则应引发 UnpicklingError

有关详细信息和使用示例,请参阅 外部对象持久性

find_class(module, name)

如有必要,导入 module 并从中返回名为 name 的对象,其中 modulename 参数为 str ] 对象。 请注意,与其名称所暗示的不同,find_class() 也用于查找函数。

子类可以覆盖它以控制对象的类型和加载方式,从而潜在地降低安全风险。 有关详细信息,请参阅 限制全局变量

class pickle.PickleBuffer(buffer)

表示可腌制数据的缓冲区的包装器。 buffer 必须是一个 buffer-providing 对象,比如一个 bytes-like object 或者一个 N 维数组。

PickleBuffer 本身就是一个缓冲区提供者,因此可以将它传递给其他需要缓冲区提供对象的 API,例如 memoryview

PickleBuffer 对象只能使用 pickle 协议 5 或更高版本进行序列化。 它们有资格进行 带外序列化

3.8 版中的新功能。

raw()

返回此缓冲区下的内存区域的 memoryview。 返回的对象是格式为 B(无符号字节)的一维 C 连续内存视图。 BufferError 如果缓冲区既不是 C 连续的,也不是 Fortran 连续的,则会引发。

release()

释放由 PickleBuffer 对象公开的底层缓冲区。


什么可以腌制和不腌制?

可以腌制以下类型:

  • NoneTrueFalse
  • 整数、浮点数、复数
  • 字符串、字节、字节数组
  • 仅包含可picklable 对象的元组、列表、集合和字典
  • 在模块顶层定义的函数(使用 def,而不是 lambda
  • 定义在模块顶层的内置函数
  • 在模块顶层定义的类
  • __dict__ 或调用 __getstate__() 的结果是可酸洗的类的实例(有关详细信息,请参阅 酸洗类实例 部分)。

尝试腌制不可腌制的对象将引发 PicklingError 异常; 发生这种情况时,可能已经将未指定数量的字节写入底层文件。 尝试腌制一个高度递归的数据结构可能会超过最大递归深度,在这种情况下将引发 RecursionError。 您可以使用 sys.setrecursionlimit() 小心地提高此限制。

请注意,函数(内置和用户定义的)由“完全限定”名称引用而不是值来腌制。 2 这意味着只腌制函数名称,以及定义函数的模块名称。 函数的代码及其任何函数属性都不会被腌制。 因此定义模块必须在 unpickling 环境中可导入,并且模块必须包含命名对象,否则将引发异常。 3

类似地,类通过命名引用进行酸洗,因此在 unpickling 环境中适用相同的限制。 请注意,类的代码或数据均未经过酸洗,因此在以下示例中,类属性 attr 在 unpickling 环境中不会恢复:

class Foo:
    attr = 'A class attribute'

picklestring = pickle.dumps(Foo)

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

类似地,当类实例被腌制时,它们的类的代码和数据不会与它们一起被腌制。 只有实例数据被腌制。 这是故意完成的,因此您可以修复类中的错误或向类添加方法,并且仍然加载使用早期版本的类创建的对象。 如果您计划拥有将看到一个类的多个版本的长期对象,那么在对象中放置一个版本号可能是值得的,以便可以通过类的 __setstate__() 方法进行适当的转换。


酸洗类实例

在本节中,我们将描述可用于定义、自定义和控制类实例的pickle 和unpickle 方式的一般机制。

在大多数情况下,不需要额外的代码来使实例可以pickle。 默认情况下,pickle 将通过自省检索实例的类和属性。 当一个类实例被 unpickled 时,它的 __init__() 方法通常是 not 调用。 默认行为首先创建一个未初始化的实例,然后恢复保存的属性。 以下代码显示了此行为的实现:

def save(obj):
    return (obj.__class__, obj.__dict__)

def load(cls, attributes):
    obj = cls.__new__(cls)
    obj.__dict__.update(attributes)
    return obj

类可以通过提供一种或几种特殊方法来改变默认行为:

object.__getnewargs_ex__()

在协议 2 和更新的协议中,实现 __getnewargs_ex__() 方法的类可以在 unpickling 时指定传递给 __new__() 方法的值。 该方法必须返回一对 (args, kwargs),其中 args 是位置参数的元组,而 kwargs 是用于构造对象的命名参数字典。 这些将在 unpickling 时传递给 __new__() 方法。

如果您的类的 __new__() 方法需要仅关键字参数,则您应该实现此方法。 否则,为了兼容性,建议实现 __getnewargs__()

3.6 版更改: __getnewargs_ex__() 现在用于协议 2 和 3。

object.__getnewargs__()

此方法的用途与 __getnewargs_ex__() 类似,但仅支持位置参数。 它必须返回一个参数元组 args,该元组将在解压时传递给 __new__() 方法。

如果定义了 __getnewargs_ex__(),则不会调用 __getnewargs__()

3.6 版更改: 在 Python 3.6 之前, __getnewargs__() 在协议 2 和 3 中被调用而不是 __getnewargs_ex__()

object.__getstate__()
类可以进一步影响它们的实例如何被腌制; 如果类定义了 __getstate__() 方法,则调用该方法并将返回的对象作为实例的内容进行腌制,而不是实例字典的内容。 如果 __getstate__() 方法不存在,则实例的 __dict__ 像往常一样被腌制。
object.__setstate__(state)

在 unpickling 时,如果该类定义了 __setstate__(),则以 unpickled 状态调用它。 在这种情况下,状态对象不需要是字典。 否则,pickled 状态必须是一个字典,并且它的项被分配给新实例的字典。

笔记

如果 __getstate__() 返回一个假值,__setstate__() 方法在 unpickling 时不会被调用。

有关如何使用方法 __getstate__()__setstate__() 的更多信息,请参阅 处理有状态对象 部分。

笔记

在 unpickling 时,可能会在实例上调用一些方法,如 __getattr__()__getattribute__()__setattr__()。 如果这些方法依赖于某些内部不变量为真,则该类型应实现 __new__() 来建立这样的不变量,因为在取消实例时不会调用 __init__()


正如我们将看到的,pickle 不直接使用上述方法。 事实上,这些方法是实现 __reduce__() 特殊方法的复制协议的一部分。 复制协议提供了一个统一的接口,用于检索酸洗和复制对象所需的数据。 4

尽管功能强大,但直接在类中实现 __reduce__() 很容易出错。 因此,类设计者应尽可能使用高级接口(即 __getnewargs_ex__()__getstate__()__setstate__())。 然而,我们将展示使用 __reduce__() 是唯一选择或导致更有效酸洗或两者兼而有之的情况。

object.__reduce__()

该接口目前定义如下。 __reduce__() 方法不接受任何参数,并且应该返回一个字符串或者最好是一个元组(返回的对象通常被称为“reduce 值”)。

如果返回字符串,则该字符串应被解释为全局变量的名称。 它应该是对象相对于其模块的本地名称; pickle 模块搜索模块命名空间以确定对象的模块。 此行为通常对单身人士有用。

返回元组时,它的长度必须介于 2 到 6 个项目之间。 可以省略可选项目,也可以提供 None 作为它们的值。 每个项目的语义按顺序排列:

  • 一个可调用对象,将被调用以创建对象的初始版本。

  • 可调用对象的参数元组。 如果可调用对象不接受任何参数,则必须给出一个空元组。

  • 可选地,对象的状态,将传递给对象的 __setstate__() 方法,如前所述。 如果对象没有这样的方法,那么该值必须是一个字典,它将被添加到对象的 __dict__ 属性中。

  • 可选地,一个迭代器(而不是一个序列)产生连续的项目。 这些项目将使用 obj.append(item) 或批量使用 obj.extend(list_of_items) 附加到对象。 这主要用于列表子类,但也可以被其他类使用,只要它们具有带有适当签名的 append()extend() 方法。 (使用 append() 还是 extend() 取决于使用的 pickle 协议版本以及要追加的项数,因此两者都必须支持。)

  • 可选地,迭代器(不是序列)产生连续的键值对。 这些项目将使用 obj[key] = value 存储到对象中。 这主要用于字典子类,但也可以被其他类使用,只要它们实现 __setitem__()

  • 可选地,具有 (obj, state) 签名的可调用对象。 这个可调用对象允许用户以编程方式控制特定对象的状态更新行为,而不是使用 obj 的静态 __setstate__() 方法。 如果不是 None,这个可调用对象将优先于 obj__setstate__()

    3.8 新功能:增加了可选的第六个元组项,(obj, state)

object.__reduce_ex__(protocol)
或者,可以定义 __reduce_ex__() 方法。 唯一的区别是此方法应采用单个整数参数,即协议版本。 定义后,pickle 会比 __reduce__() 方法更喜欢它。 此外,__reduce__() 自动成为扩展版本的同义词。 此方法的主要用途是为较旧的 Python 版本提供向后兼容的 reduce 值。

外部对象的持久性

为了对象持久性的好处,pickle 模块支持对pickle 数据流之外的对象的引用的概念。 此类对象由持久 ID 引用,该 ID 应该是一串字母数字字符(对于协议 0)5 或只是一个任意对象(对于任何更新的协议)。

pickle 模块未定义此类持久 ID 的解析; 它将将此分辨率委托给pickler 和unpickler 上的用户定义方法,分别为persistent_id()persistent_load()

要pickle具有外部持久ID的对象,pickler必须有一个自定义的persistent_id()方法,该方法将一个对象作为参数并返回None或该对象的持久ID。 当返回 None 时,pickler 只是像平常一样腌制对象。 当返回一个持久 ID 字符串时,pickler 将pickle 该对象以及一个标记,以便 unpickler 将其识别为持久 ID。

要解开外部对象,解开器必须有一个自定义的 persistent_load() 方法,该方法接受一个持久 ID 对象并返回引用的对象。

这是一个综合示例,展示了如何使用持久 ID 通过引用来pickle外部对象。

# Simple example presenting how persistent ID can be used to pickle
# external objects by reference.

import pickle
import sqlite3
from collections import namedtuple

# Simple class representing a record in our database.
MemoRecord = namedtuple("MemoRecord", "key, task")

class DBPickler(pickle.Pickler):

    def persistent_id(self, obj):
        # Instead of pickling MemoRecord as a regular class instance, we emit a
        # persistent ID.
        if isinstance(obj, MemoRecord):
            # Here, our persistent ID is simply a tuple, containing a tag and a
            # key, which refers to a specific record in the database.
            return ("MemoRecord", obj.key)
        else:
            # If obj does not have a persistent ID, return None. This means obj
            # needs to be pickled as usual.
            return None


class DBUnpickler(pickle.Unpickler):

    def __init__(self, file, connection):
        super().__init__(file)
        self.connection = connection

    def persistent_load(self, pid):
        # This method is invoked whenever a persistent ID is encountered.
        # Here, pid is the tuple returned by DBPickler.
        cursor = self.connection.cursor()
        type_tag, key_id = pid
        if type_tag == "MemoRecord":
            # Fetch the referenced record from the database and return it.
            cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),))
            key, task = cursor.fetchone()
            return MemoRecord(key, task)
        else:
            # Always raises an error if you cannot return the correct object.
            # Otherwise, the unpickler will think None is the object referenced
            # by the persistent ID.
            raise pickle.UnpicklingError("unsupported persistent object")


def main():
    import io
    import pprint

    # Initialize and populate our database.
    conn = sqlite3.connect(":memory:")
    cursor = conn.cursor()
    cursor.execute("CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)")
    tasks = (
        'give food to fish',
        'prepare group meeting',
        'fight with a zebra',
        )
    for task in tasks:
        cursor.execute("INSERT INTO memos VALUES(NULL, ?)", (task,))

    # Fetch the records to be pickled.
    cursor.execute("SELECT * FROM memos")
    memos = [MemoRecord(key, task) for key, task in cursor]
    # Save the records using our custom DBPickler.
    file = io.BytesIO()
    DBPickler(file).dump(memos)

    print("Pickled records:")
    pprint.pprint(memos)

    # Update a record, just for good measure.
    cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1")

    # Load the records from the pickle data stream.
    file.seek(0)
    memos = DBUnpickler(file, conn).load()

    print("Unpickled records:")
    pprint.pprint(memos)


if __name__ == '__main__':
    main()

调度表

如果您想自定义某些类的酸洗而不干扰任何其他依赖酸洗的代码,那么您可以创建一个带有私有调度表的酸洗器。

copyreg 模块管理的全局调度表可作为 copyreg.dispatch_table 使用。 因此,可以选择使用 copyreg.dispatch_table 的修改副本作为私有调度表。

例如

f = io.BytesIO()
p = pickle.Pickler(f)
p.dispatch_table = copyreg.dispatch_table.copy()
p.dispatch_table[SomeClass] = reduce_SomeClass

创建一个 pickle.Pickler 的实例,带有一个专门处理 SomeClass 类的私有调度表。 或者,代码

class MyPickler(pickle.Pickler):
    dispatch_table = copyreg.dispatch_table.copy()
    dispatch_table[SomeClass] = reduce_SomeClass
f = io.BytesIO()
p = MyPickler(f)

执行相同的操作,但 MyPickler 的所有实例将默认共享相同的调度表。 使用 copyreg 模块的等效代码是

copyreg.pickle(SomeClass, reduce_SomeClass)
f = io.BytesIO()
p = pickle.Pickler(f)

处理有状态对象

这是一个示例,展示了如何修改类的酸洗行为。 TextReader 类打开一个文本文件,并在每次调用其 readline() 方法时返回行号和行内容。 如果一个 TextReader 实例被腌制,则所有属性 文件对象成员被保存。 当实例被 unpickle 时,文件被重新打开,并从最后一个位置继续读取。 __setstate__()__getstate__() 方法用于实现此行为。

class TextReader:
    """Print and number lines in a text file."""

    def __init__(self, filename):
        self.filename = filename
        self.file = open(filename)
        self.lineno = 0

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

    def __getstate__(self):
        # Copy the object's state from self.__dict__ which contains
        # all our instance attributes. Always use the dict.copy()
        # method to avoid modifying the original state.
        state = self.__dict__.copy()
        # Remove the unpicklable entries.
        del state['file']
        return state

    def __setstate__(self, state):
        # Restore instance attributes (i.e., filename and lineno).
        self.__dict__.update(state)
        # Restore the previously opened file's state. To do so, we need to
        # reopen it and read from it until the line count is restored.
        file = open(self.filename)
        for _ in range(self.lineno):
            file.readline()
        # Finally, save the file.
        self.file = file

示例用法可能是这样的:

>>> reader = TextReader("hello.txt")
>>> reader.readline()
'1: Hello world!'
>>> reader.readline()
'2: I am line number two.'
>>> new_reader = pickle.loads(pickle.dumps(reader))
>>> new_reader.readline()
'3: Goodbye!'

类型、函数和其他对象的自定义缩减

3.8 版中的新功能。


有时, dispatch_table 可能不够灵活。 特别是我们可能希望根据对象类型以外的其他标准自定义酸洗,或者我们可能希望自定义函数和类的酸洗。

对于这些情况,可以从 Picker 类继承子类并实现 reducer_override() 方法。 这个方法可以返回一个任意的归约元组(见 __reduce__())。 它也可以返回 NotImplemented 以回退到传统行为。

如果同时定义了 dispatch_tablereducer_override(),那么 reducer_override() 方法优先。

笔记

出于性能原因,可能不会为以下对象调用 reducer_override()NoneTrueFalse的确切实例int, float, bytes, str, dict, set, X257X]、 列表元组


这是一个简单的例子,我们允许酸洗和重建给定的类:

import io
import pickle

class MyClass:
    my_attribute = 1

class MyPickler(pickle.Pickler):
    def reducer_override(self, obj):
        """Custom reducer for MyClass."""
        if getattr(obj, "__name__", None) == "MyClass":
            return type, (obj.__name__, obj.__bases__,
                          {'my_attribute': obj.my_attribute})
        else:
            # For any other object, fallback to usual reduction
            return NotImplemented

f = io.BytesIO()
p = MyPickler(f)
p.dump(MyClass)

del MyClass

unpickled_class = pickle.loads(f.getvalue())

assert isinstance(unpickled_class, type)
assert unpickled_class.__name__ == "MyClass"
assert unpickled_class.my_attribute == 1

带外缓冲器

3.8 版中的新功能。


在某些情况下,pickle 模块用于传输大量数据。 因此,尽量减少内存副本的数量以保持性能和资源消耗可能很重要。 但是,pickle 模块的正常操作,因为它将对象的图形结构转换为字节的顺序流,本质上涉及将数据复制到pickle 流或从pickle 流复制数据。

如果 provider(要传输的对象类型的实现)和 consumer(通信系统的实现)都支持带外pickle 协议 5 及更高版本提供的传输设施。

提供者 API

要被pickle的大数据对象必须实现一个专用于协议5及更高版本的__reduce_ex__()方法,该方法返回一个PickleBuffer实例(而不是例如 一个 bytes 对象)用于任何大数据。

PickleBuffer 对象 发出信号 表明底层缓冲区有资格进行带外数据传输。 这些对象与 pickle 模块的正常使用保持兼容。 但是,消费者也可以选择告诉 pickle 他们将自己处理这些缓冲区。


消费者API

通信系统可以启用对序列化对象图时生成的 PickleBuffer 对象的自定义处理。

在发送端,它需要将 buffer_callback 参数传递给 Pickler(或 dump()dumps() 函数),它将在酸洗对象图时生成的每个 PickleBuffer 被调用。 buffer_callback 累积的缓冲区不会看到它们的数据复制到pickle 流中,只会插入一个廉价的标记。

在接收端,它需要将 buffers 参数传递给 Unpickler(或 load()loads() 函数),这是传递给 buffer_callback 的缓冲区的可迭代对象。 该可迭代对象应该按照传递给 buffer_callback 的相同顺序生成缓冲区。 这些缓冲区将提供对象的重构器所期望的数据,这些对象的酸洗产生了原始的 PickleBuffer 对象。

在发送端和接收端之间,通信系统可以自由地实现自己的带外缓冲区传输机制。 潜在的优化包括使用共享内存或依赖于数据类型的压缩。


例子

这是一个简单的例子,我们实现了一个能够参与带外缓冲区酸洗的 bytearray 子类:

class ZeroCopyByteArray(bytearray):

    def __reduce_ex__(self, protocol):
        if protocol >= 5:
            return type(self)._reconstruct, (PickleBuffer(self),), None
        else:
            # PickleBuffer is forbidden with pickle protocols <= 4.
            return type(self)._reconstruct, (bytearray(self),)

    @classmethod
    def _reconstruct(cls, obj):
        with memoryview(obj) as m:
            # Get a handle over the original buffer object
            obj = m.obj
            if type(obj) is cls:
                # Original buffer object is a ZeroCopyByteArray, return it
                # as-is.
                return obj
            else:
                return cls(obj)

重构器(_reconstruct 类方法)返回缓冲区的提供对象,如果它具有正确的类型。 这是在这个玩具示例上模拟零复制行为的简单方法。

在消费者方面,我们可以用通常的方式腌制这些对象,反序列化时会给我们一个原始对象的副本:

b = ZeroCopyByteArray(b"abc")
data = pickle.dumps(b, protocol=5)
new_b = pickle.loads(data)
print(b == new_b)  # True
print(b is new_b)  # False: a copy was made

但是如果我们传递一个 buffer_callback 然后在反序列化时返回累积的缓冲区,我们就可以取回原始对象:

b = ZeroCopyByteArray(b"abc")
buffers = []
data = pickle.dumps(b, protocol=5, buffer_callback=buffers.append)
new_b = pickle.loads(data, buffers=buffers)
print(b == new_b)  # True
print(b is new_b)  # True: no copy was made

此示例受到 bytearray 分配自己的内存这一事实的限制:您不能创建由另一个对象的内存支持的 bytearray 实例。 但是,第三方数据类型(例如 NumPy 数组)没有此限制,并且在不同的进程或系统之间传输时允许使用零副本酸洗(或制作尽可能少的副本)。

也可以看看

PEP 574 – 带外数据的 Pickle 协议 5


限制全局变量

默认情况下,unpickling 将导入它在 pickle 数据中找到的任何类或函数。 对于许多应用程序,这种行为是不可接受的,因为它允许 unpickler 导入和调用任意代码。 只需考虑加载时这个手工制作的pickle数据流的作用:

>>> import pickle
>>> pickle.loads(b"cos\nsystem\n(S'echo hello world'\ntR.")
hello world
0

在这个例子中,unpickler 导入 os.system() 函数,然后应用字符串参数“echo hello world”。 尽管此示例无害,但不难想象可能会损坏您的系统的示例。

出于这个原因,您可能希望通过自定义 Unpickler.find_class() 来控制什么被取消。 与其名称所暗示的不同,只要请求全局(即类或函数),就会调用 Unpickler.find_class()。 因此,可以完全禁止全局变量或将它们限制为安全子集。

下面是一个 unpickler 的例子,它只允许加载 builtins 模块中的几个安全类:

import builtins
import io
import pickle

safe_builtins = {
    'range',
    'complex',
    'set',
    'frozenset',
    'slice',
}

class RestrictedUnpickler(pickle.Unpickler):

    def find_class(self, module, name):
        # Only allow safe classes from builtins.
        if module == "builtins" and name in safe_builtins:
            return getattr(builtins, name)
        # Forbid everything else.
        raise pickle.UnpicklingError("global '%s.%s' is forbidden" %
                                     (module, name))

def restricted_loads(s):
    """Helper function analogous to pickle.loads()."""
    return RestrictedUnpickler(io.BytesIO(s)).load()

我们的 unpickler 工作的示例用法旨在:

>>> restricted_loads(pickle.dumps([1, 2, range(15)]))
[1, 2, range(0, 15)]
>>> restricted_loads(b"cos\nsystem\n(S'echo hello world'\ntR.")
Traceback (most recent call last):
  ...
pickle.UnpicklingError: global 'os.system' is forbidden
>>> restricted_loads(b'cbuiltins\neval\n'
...                  b'(S\'getattr(__import__("os"), "system")'
...                  b'("echo hello world")\'\ntR.')
Traceback (most recent call last):
  ...
pickle.UnpicklingError: global 'builtins.eval' is forbidden

正如我们的例子所示,你必须小心你允许去腌制的东西。 因此,如果担心安全性,您可能需要考虑替代方案,例如 xmlrpc.client 中的编组 API 或第三方解决方案。


表现

pickle 协议的最新版本(从协议 2 开始)为几个常见功能和内置类型提供了高效的二进制编码。 此外,pickle 模块有一个用 C 编写的透明优化器。


例子

对于最简单的代码,使用 dump()load() 函数。

import pickle

# An arbitrary collection of objects supported by pickle.
data = {
    'a': [1, 2.0, 3, 4+6j],
    'b': ("character string", b"byte string"),
    'c': {None, True, False}
}

with open('data.pickle', 'wb') as f:
    # Pickle the 'data' dictionary using the highest protocol available.
    pickle.dump(data, f, pickle.HIGHEST_PROTOCOL)

以下示例读取生成的腌制数据。

import pickle

with open('data.pickle', 'rb') as f:
    # The protocol version used is detected automatically, so we do not
    # have to specify it.
    data = pickle.load(f)

也可以看看

模块 copyreg
扩展类型的 Pickle 接口构造函数注册。
模块 pickletools
用于处理和分析腌制数据的工具。
模块 搁架
对象的索引数据库; 使用 pickle
模块复制
浅层和深层对象复制。
模块元帅
内置类型的高性能序列化。


脚注

1
不要将其与 marshal 模块混淆
2
这就是为什么 lambda 函数不能被腌制的原因:所有 lambda 函数共享同一个名称:<lambda>
3
引发的异常可能是 ImportErrorAttributeError,但也可能是别的东西。
4
copy 模块使用这个协议进行浅拷贝和深拷贝操作。
5
对字母数字字符的限制是因为协议 0 中的持久 ID 由换行符分隔。 因此,如果持久 ID 中出现任何类型的换行符,则生成的 pickle 将变得不可读。