2011-08-11 14:10:41 -04:00
|
|
|
PEP: 3154
|
|
|
|
Title: Pickle protocol version 4
|
|
|
|
Version: $Revision$
|
|
|
|
Last-Modified: $Date$
|
|
|
|
Author: Antoine Pitrou <solipsis@pitrou.net>
|
2013-11-23 13:06:53 -05:00
|
|
|
Status: Final
|
2011-08-11 14:10:41 -04:00
|
|
|
Type: Standards Track
|
|
|
|
Content-Type: text/x-rst
|
2021-02-09 11:54:26 -05:00
|
|
|
Created: 11-Aug-2011
|
2013-04-27 07:24:45 -04:00
|
|
|
Python-Version: 3.4
|
2022-03-09 11:04:44 -05:00
|
|
|
Post-History: `12-Aug-2011 <https://mail.python.org/pipermail/python-dev/2011-August/112821.html>`__
|
2013-11-20 19:49:24 -05:00
|
|
|
Resolution: https://mail.python.org/pipermail/python-dev/2013-November/130439.html
|
2011-08-11 14:10:41 -04:00
|
|
|
|
|
|
|
|
|
|
|
Abstract
|
|
|
|
========
|
|
|
|
|
2011-08-12 13:38:10 -04:00
|
|
|
Data serialized using the pickle module must be portable across Python
|
2011-10-30 07:45:18 -04:00
|
|
|
versions. It should also support the latest language features as well
|
|
|
|
as implementation-specific features. For this reason, the pickle
|
|
|
|
module knows about several protocols (currently numbered from 0 to 3),
|
|
|
|
each of which appeared in a different Python version. Using a
|
|
|
|
low-numbered protocol version allows to exchange data with old Python
|
|
|
|
versions, while using a high-numbered protocol allows access to newer
|
|
|
|
features and sometimes more efficient resource use (both CPU time
|
|
|
|
required for (de)serializing, and disk size / network bandwidth
|
|
|
|
required for data transfer).
|
2011-08-11 14:10:41 -04:00
|
|
|
|
|
|
|
|
|
|
|
Rationale
|
|
|
|
=========
|
|
|
|
|
2011-10-30 07:45:18 -04:00
|
|
|
The latest current protocol, coincidentally named protocol 3, appeared
|
|
|
|
with Python 3.0 and supports the new incompatible features in the
|
|
|
|
language (mainly, unicode strings by default and the new bytes
|
|
|
|
object). The opportunity was not taken at the time to improve the
|
|
|
|
protocol in other ways.
|
2011-08-11 14:10:41 -04:00
|
|
|
|
2013-04-27 07:24:45 -04:00
|
|
|
This PEP is an attempt to foster a number of incremental improvements
|
|
|
|
in a new pickle protocol version. The PEP process is used in order to
|
|
|
|
gather as many improvements as possible, because the introduction of a
|
|
|
|
new pickle protocol should be a rare occurrence.
|
2011-08-11 14:10:41 -04:00
|
|
|
|
|
|
|
|
2013-04-26 16:57:06 -04:00
|
|
|
Proposed changes
|
|
|
|
================
|
|
|
|
|
|
|
|
Framing
|
|
|
|
-------
|
|
|
|
|
|
|
|
Traditionally, when unpickling an object from a stream (by calling
|
|
|
|
``load()`` rather than ``loads()``), many small ``read()``
|
|
|
|
calls can be issued on the file-like object, with a potentially huge
|
|
|
|
performance impact.
|
|
|
|
|
|
|
|
Protocol 4, by contrast, features binary framing. The general structure
|
|
|
|
of a pickle is thus the following::
|
|
|
|
|
|
|
|
+------+------+
|
2013-11-20 18:58:38 -05:00
|
|
|
| 0x80 | 0x04 | protocol header (2 bytes)
|
|
|
|
+------+------+
|
|
|
|
| OP | FRAME opcode (1 byte)
|
2013-04-26 16:57:06 -04:00
|
|
|
+------+------+-----------+
|
2013-04-26 17:13:23 -04:00
|
|
|
| MM MM MM MM MM MM MM MM | frame size (8 bytes, little-endian)
|
2013-04-26 16:57:06 -04:00
|
|
|
+------+------------------+
|
2013-11-20 18:58:38 -05:00
|
|
|
| .... | first frame contents (M bytes)
|
|
|
|
+------+
|
|
|
|
| OP | FRAME opcode (1 byte)
|
2013-04-26 16:57:06 -04:00
|
|
|
+------+------+-----------+
|
2013-04-26 17:13:23 -04:00
|
|
|
| NN NN NN NN NN NN NN NN | frame size (8 bytes, little-endian)
|
2013-04-26 16:57:06 -04:00
|
|
|
+------+------------------+
|
2013-11-20 18:58:38 -05:00
|
|
|
| .... | second frame contents (N bytes)
|
2013-04-26 16:57:06 -04:00
|
|
|
+------+
|
|
|
|
etc.
|
|
|
|
|
|
|
|
To keep the implementation simple, it is forbidden for a pickle opcode
|
2013-04-26 17:18:25 -04:00
|
|
|
to straddle frame boundaries. The pickler takes care not to produce such
|
2013-04-26 17:10:16 -04:00
|
|
|
pickles, and the unpickler refuses them. Also, there is no "last frame"
|
|
|
|
marker. The last frame is simply the one which ends with a STOP opcode.
|
2013-04-26 16:57:06 -04:00
|
|
|
|
2013-04-27 07:24:45 -04:00
|
|
|
A well-written C implementation doesn't need additional memory copies
|
|
|
|
for the framing layer, preserving general (un)pickling efficiency.
|
|
|
|
|
2013-04-26 17:10:16 -04:00
|
|
|
.. note::
|
|
|
|
|
2013-04-27 07:24:45 -04:00
|
|
|
How the pickler decides to partition the pickle stream into frames is an
|
|
|
|
implementation detail. For example, "closing" a frame as soon as it
|
|
|
|
reaches ~64 KiB is a reasonable choice for both performance and pickle
|
|
|
|
size overhead.
|
2011-08-11 14:10:41 -04:00
|
|
|
|
2013-04-26 16:57:06 -04:00
|
|
|
Binary encoding for all opcodes
|
|
|
|
-------------------------------
|
|
|
|
|
|
|
|
The GLOBAL opcode, which is still used in protocol 3, uses the
|
|
|
|
so-called "text" mode of the pickle protocol, which involves looking
|
|
|
|
for newlines in the pickle stream. It also complicates the implementation
|
|
|
|
of binary framing.
|
|
|
|
|
|
|
|
Protocol 4 forbids use of the GLOBAL opcode and replaces it with
|
2020-03-23 00:51:49 -04:00
|
|
|
STACK_GLOBAL, a new opcode which takes its operand from the stack.
|
2013-04-26 16:57:06 -04:00
|
|
|
|
|
|
|
Serializing more "lookupable" objects
|
|
|
|
-------------------------------------
|
|
|
|
|
|
|
|
By default, pickle is only able to serialize module-global functions and
|
|
|
|
classes. Supporting other kinds of objects, such as unbound methods [4]_,
|
|
|
|
is a common request. Actually, third-party support for some of them, such
|
|
|
|
as bound methods, is implemented in the multiprocessing module [5]_.
|
|
|
|
|
|
|
|
The ``__qualname__`` attribute from :pep:`3155` makes it possible to
|
2020-03-23 00:51:49 -04:00
|
|
|
lookup many more objects by name. Making the STACK_GLOBAL opcode accept
|
2013-11-16 13:10:10 -05:00
|
|
|
dot-separated names would allow the standard pickle implementation to
|
|
|
|
support all those kinds of objects.
|
2013-04-26 16:57:06 -04:00
|
|
|
|
|
|
|
64-bit opcodes for large objects
|
|
|
|
--------------------------------
|
2011-08-11 14:10:41 -04:00
|
|
|
|
2011-10-30 07:45:18 -04:00
|
|
|
Current protocol versions export object sizes for various built-in
|
|
|
|
types (str, bytes) as 32-bit ints. This forbids serialization of
|
|
|
|
large data [1]_. New opcodes are required to support very large bytes
|
|
|
|
and str objects.
|
2011-08-11 14:10:41 -04:00
|
|
|
|
|
|
|
Native opcodes for sets and frozensets
|
|
|
|
--------------------------------------
|
|
|
|
|
2011-10-30 07:45:18 -04:00
|
|
|
Many common built-in types (such as str, bytes, dict, list, tuple)
|
|
|
|
have dedicated opcodes to improve resource consumption when
|
|
|
|
serializing and deserializing them; however, sets and frozensets
|
|
|
|
don't. Adding such opcodes would be an obvious improvement. Also,
|
|
|
|
dedicated set support could help remove the current impossibility of
|
|
|
|
pickling self-referential sets [2]_.
|
2011-08-11 14:10:41 -04:00
|
|
|
|
2011-08-15 21:27:53 -04:00
|
|
|
Calling __new__ with keyword arguments
|
|
|
|
--------------------------------------
|
|
|
|
|
2013-11-20 20:06:06 -05:00
|
|
|
Currently, classes whose ``__new__`` mandates the use of keyword-only
|
2011-10-30 07:45:18 -04:00
|
|
|
arguments can not be pickled (or, rather, unpickled) [3]_. Both a new
|
2013-11-20 20:06:06 -05:00
|
|
|
special method (``__getnewargs_ex__``) and a new opcode (NEWOBJ_EX)
|
|
|
|
are needed. The ``__getnewargs_ex__`` method, if it exists, must
|
|
|
|
return a two-tuple ``(args, kwargs)`` where the first item is the
|
|
|
|
tuple of positional arguments and the second item is the dict of
|
|
|
|
keyword arguments for the class's ``__new__`` method.
|
2011-08-15 21:27:53 -04:00
|
|
|
|
2011-08-12 11:14:23 -04:00
|
|
|
Better string encoding
|
|
|
|
----------------------
|
|
|
|
|
2011-10-30 07:45:18 -04:00
|
|
|
Short str objects currently have their length coded as a 4-bytes
|
|
|
|
integer, which is wasteful. A specific opcode with a 1-byte length
|
|
|
|
would make many pickles smaller.
|
2011-08-11 14:10:41 -04:00
|
|
|
|
2013-11-20 18:58:38 -05:00
|
|
|
Smaller memoization
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
The PUT opcodes all require an explicit index to select in which entry
|
|
|
|
of the memo dictionary the top-of-stack is memoized. However, in practice
|
|
|
|
those numbers are allocated in sequential order. A new opcode, MEMOIZE,
|
|
|
|
will instead store the top-of-stack in at the index equal to the current
|
|
|
|
size of the memo dictionary. This allows for shorter pickles, since PUT
|
|
|
|
opcodes are emitted for all non-atomic datatypes.
|
|
|
|
|
2011-08-11 14:10:41 -04:00
|
|
|
|
2013-11-16 13:08:03 -05:00
|
|
|
Summary of new opcodes
|
|
|
|
======================
|
|
|
|
|
2013-11-16 13:10:10 -05:00
|
|
|
These reflect the state of the proposed implementation (thanks mostly
|
|
|
|
to Alexandre Vassalotti's work):
|
|
|
|
|
2013-11-20 18:58:38 -05:00
|
|
|
* ``FRAME``: introduce a new frame (followed by the 8-byte frame size
|
|
|
|
and the frame contents).
|
|
|
|
|
2013-11-16 13:08:03 -05:00
|
|
|
* ``SHORT_BINUNICODE``: push a utf8-encoded str object with a one-byte
|
|
|
|
size prefix (therefore less than 256 bytes long).
|
|
|
|
|
2016-05-03 06:52:22 -04:00
|
|
|
* ``BINUNICODE8``: push a utf8-encoded str object with an eight-byte
|
2013-11-16 13:08:03 -05:00
|
|
|
size prefix (for strings longer than 2**32 bytes, which therefore cannot
|
|
|
|
be serialized using ``BINUNICODE``).
|
|
|
|
|
2016-05-03 06:52:22 -04:00
|
|
|
* ``BINBYTES8``: push a bytes object with an eight-byte size prefix
|
2013-11-16 13:08:03 -05:00
|
|
|
(for bytes objects longer than 2**32 bytes, which therefore cannot be
|
|
|
|
serialized using ``BINBYTES``).
|
|
|
|
|
|
|
|
* ``EMPTY_SET``: push a new empty set object on the stack.
|
|
|
|
|
|
|
|
* ``ADDITEMS``: add the topmost stack items to the set (to be used with
|
|
|
|
``EMPTY_SET``).
|
|
|
|
|
|
|
|
* ``FROZENSET``: create a frozenset object from the topmost stack items,
|
|
|
|
and push it on the stack.
|
|
|
|
|
|
|
|
* ``NEWOBJ_EX``: take the three topmost stack items ``cls``, ``args``
|
|
|
|
and ``kwargs``, and push the result of calling
|
|
|
|
``cls.__new__(*args, **kwargs)``.
|
|
|
|
|
|
|
|
* ``STACK_GLOBAL``: take the two topmost stack items ``module_name`` and
|
|
|
|
``qualname``, and push the result of looking up the dotted ``qualname``
|
|
|
|
in the module named ``module_name``.
|
|
|
|
|
2013-11-20 18:58:38 -05:00
|
|
|
* ``MEMOIZE``: store the top-of-stack object in the memo dictionary with
|
|
|
|
an index equal to the current size of the memo dictionary.
|
|
|
|
|
2013-11-16 13:08:03 -05:00
|
|
|
|
2013-04-27 07:24:45 -04:00
|
|
|
Alternative ideas
|
|
|
|
=================
|
|
|
|
|
|
|
|
Prefetching
|
|
|
|
-----------
|
|
|
|
|
|
|
|
Serhiy Storchaka suggested to replace framing with a special PREFETCH
|
|
|
|
opcode (with a 2- or 4-bytes argument) to declare known pickle chunks
|
|
|
|
explicitly. Large data may be pickled outside such chunks. A naïve
|
|
|
|
unpickler should be able to skip the PREFETCH opcode and still decode
|
|
|
|
pickles properly, but good error handling would require checking that
|
|
|
|
the PREFETCH length falls on an opcode boundary.
|
|
|
|
|
|
|
|
|
2011-08-11 14:10:41 -04:00
|
|
|
Acknowledgments
|
|
|
|
===============
|
|
|
|
|
2013-04-27 07:24:45 -04:00
|
|
|
In alphabetic order:
|
|
|
|
|
2022-01-21 06:03:51 -05:00
|
|
|
* Alexandre Vassalotti, for starting the second :pep:`3154` implementation [6]_
|
2013-04-27 07:24:45 -04:00
|
|
|
|
|
|
|
* Serhiy Storchaka, for discussing the framing proposal [6]_
|
|
|
|
|
2022-01-21 06:03:51 -05:00
|
|
|
* Stefan Mihaila, for starting the first :pep:`3154` implementation as a
|
2013-04-27 07:24:45 -04:00
|
|
|
Google Summer of Code project mentored by Alexandre Vassalotti [7]_.
|
2011-08-11 14:10:41 -04:00
|
|
|
|
|
|
|
|
|
|
|
References
|
|
|
|
==========
|
|
|
|
|
|
|
|
.. [1] "pickle not 64-bit ready":
|
|
|
|
http://bugs.python.org/issue11564
|
|
|
|
|
|
|
|
.. [2] "Cannot pickle self-referencing sets":
|
|
|
|
http://bugs.python.org/issue9269
|
|
|
|
|
2011-08-15 21:27:53 -04:00
|
|
|
.. [3] "pickle/copyreg doesn't support keyword only arguments in __new__":
|
|
|
|
http://bugs.python.org/issue4727
|
|
|
|
|
2011-12-02 14:19:29 -05:00
|
|
|
.. [4] "pickle should support methods":
|
2011-08-15 21:27:53 -04:00
|
|
|
http://bugs.python.org/issue9276
|
2011-08-11 14:10:41 -04:00
|
|
|
|
2011-12-02 14:19:29 -05:00
|
|
|
.. [5] Lib/multiprocessing/forking.py:
|
|
|
|
http://hg.python.org/cpython/file/baea9f5f973c/Lib/multiprocessing/forking.py#l54
|
|
|
|
|
2013-04-27 07:24:45 -04:00
|
|
|
.. [6] Implement PEP 3154, by Alexandre Vassalotti
|
|
|
|
http://bugs.python.org/issue17810
|
|
|
|
|
|
|
|
.. [7] Implement PEP 3154, by Stefan Mihaila
|
|
|
|
http://bugs.python.org/issue15642
|
|
|
|
|
2011-10-30 07:45:18 -04:00
|
|
|
|
2011-08-11 14:10:41 -04:00
|
|
|
Copyright
|
|
|
|
=========
|
|
|
|
|
|
|
|
This document has been placed in the public domain.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
..
|
|
|
|
Local Variables:
|
|
|
|
mode: indented-text
|
|
|
|
indent-tabs-mode: nil
|
|
|
|
sentence-end-double-space: t
|
|
|
|
fill-column: 70
|
|
|
|
coding: utf-8
|
|
|
|
End:
|