"pickle" --- Python object serialization
****************************************

**Código fuente:** Lib/pickle.py

======================================================================

The "pickle" module implements binary protocols for serializing and
de-serializing a Python object structure.  *"Pickling"* is the process
whereby a Python object hierarchy is converted into a byte stream, and
*"unpickling"* is the inverse operation, whereby a byte stream (from a
*binary file* or *bytes-like object*) is converted back into an object
hierarchy.  Pickling (and unpickling) is alternatively known as
"serialization", "marshalling," [1] or "flattening"; however, to avoid
confusion, the terms used here are "pickling" and "unpickling".

Advertencia:

  El modulo "pickle" **no es seguro**. Solo deserialize con *pickle*
  los datos en los que confía.Es posible construir datos maliciosos
  con *pickle* que **ejecuten código arbitrario durante el proceso de
  `unpickling`**. Nunca deserialize datos con *pickle* que podrían
  haber venido de una fuente no confiable, o que podrían haber sido
  manipulados.Considere firmar los datos con "hmac" si necesita
  asegurarse de que no hayan sido alterados.Los formatos de
  serialización más seguros como "json" pueden ser más apropiados si
  está procesando datos no confiables. Ver Comparación con json.


Relación con otros módulos de Python
====================================


Comparación con "marshal"
-------------------------

Python has a more primitive serialization module called "marshal", but
in general "pickle" should always be the preferred way to serialize
Python objects.  "marshal" exists primarily to support Python's ".pyc"
files.

The "pickle" module differs from "marshal" in several significant
ways:

* "marshal" cannot be used to serialize user-defined classes and their
  instances.  "pickle" 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 pickled.

* The "marshal" serialization format is not guaranteed to be portable
  across Python versions.  Because its primary job in life is to
  support ".pyc" files, the Python implementers reserve the right to
  change the serialization format in non-backwards compatible ways
  should the need arise. The "pickle" 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.


Comparación con "json"
----------------------

Existen diferencias fundamentales entre los protocolos pickle y JSON
(JavaScript Object Notation):

* JSON es un formato de serialización de texto (genera texto unicode,
  aunque la mayoría de las veces se codifica a "utf-8"), mientras que
  *pickle* es un formato de serialización binario;

* JSON es legible por humanos, mientras que *pickle* no lo es;

* JSON es interoperable y ampliamente utilizado fuera del ecosistema
  de Python, mientras que *pickle* es específico de Python;

* JSON, por defecto, solo puede representar un subconjunto de los
  tipos integrados de Python, y no clases personalizadas; *pickle*
  puede representar un número extremadamente grande de tipos de Python
  (muchos de ellos automáticamente, mediante el uso inteligente de la
  introspección de objetos en Python; los casos complejos se pueden
  abordar implementando API de objetos específicos, specific object
  APIs);

* A diferencia de *pickle*, deserializar JSON no confiable no crea en
  sí mismo una vulnerabilidad de ejecución de código arbitraria.

Ver también:

  El modulo "json": un módulo de la biblioteca estándar que permite la
  serialización y deserialización de JSON.


Formato de flujo de datos
=========================

The data format used by "pickle" is Python-specific.  This has the
advantage that there are no restrictions imposed by external standards
such as JSON (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 "pickle" data format uses a relatively compact binary
representation.  If you need optimal size characteristics, you can
efficiently compress pickled data.

The module "pickletools" contains tools for analyzing data streams
generated by "pickle".  "pickletools" source code has extensive
comments about opcodes used by pickle protocols.

Actualmente hay 6 protocolos diferentes que se pueden utilizar para
serializar con *pickle*. Cuanto mayor sea el protocolo utilizado, más
reciente será la versión de Python necesaria para leer el *pickle*
producido.

* La versión 0 del protocolo es el protocolo original "legible para
  humanos" y es compatible con versiones anteriores de Python.

* La versión 1 del protocolo es un formato binario antiguo que también
  es compatible con versiones anteriores de Python.

* La versión 2 del protocolo se introdujo en Python 2.3. Proporciona
  un serializado con pickle mucho más eficiente de *new-style
  classes*. Consulte **PEP 307** para obtener información sobre las
  mejoras que trae el protocolo 2.

* Se agregó la versión 3 del protocolo en Python 3.0.  Tiene soporte
  explícito para objetos "bytes" y no puede ser deserializado con
  *pickle* por Python 2.x.  Este era el protocolo predeterminado en
  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.  This was the default protocol in Python 3.8--
  3.13. Refer to **PEP 3154** for information about improvements
  brought by protocol 4.

* Protocol version 5 was added in Python 3.8.  It adds support for
  out-of-band data and speedup for in-band data.  It is the default
  protocol starting with Python 3.14.  Refer to **PEP 574** for
  information about improvements brought by protocol 5.

Nota:

  Serialization is a more primitive notion than persistence; although
  "pickle" 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 "pickle" 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
  provides a simple interface to pickle and unpickle objects on DBM-
  style database files.


Interfaz del módulo
===================

Para serializar una jerarquía de objetos, simplemente llame a la
función "dumps()". De manera similar, para deserializar un flujo de
datos, llama a la función "loads()". Sin embargo, si desea tener más
control sobre la serialización y la deserialización, puede crear un
objeto "Pickler" o "Unpickler", respectivamente.

The "pickle" module provides the following constants:

pickle.HIGHEST_PROTOCOL

   Un entero, la versión de protocolo (protocol version) más alta
   disponible.  Este valor se puede pasar como un valor de *protocolo*
   a las funciones "dump()" y "dumps()" así como al constructor
   "Pickler".

pickle.DEFAULT_PROTOCOL

   An integer, the default protocol version used for pickling.  May be
   less than "HIGHEST_PROTOCOL".  Currently the default protocol is 5,
   introduced in Python 3.8 and incompatible with previous versions.
   This version introduces support for out-of-band buffers, where
   **PEP 3118**-compatible data can be transmitted separately from the
   main pickle stream.

   Distinto en la versión 3.0: El protocolo predeterminado es 3.

   Distinto en la versión 3.8: El protocolo predeterminado es 4.

   Distinto en la versión 3.14: The default protocol is 5.

The "pickle" module provides the following functions to make the
pickling process more convenient:

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

   Escribe la representación *pickle* del objeto *obj* en el *archivo*
   abierto *file object*.  Esto es equivalente a "Pickler(file,
   protocol).dump(obj)".

   Los argumentos *file*, *protocol*, *fix_imports* y
   *buffer_callback* tienen el mismo significado que en el constructor
   "Pickler".

   Distinto en la versión 3.8: Se agregó el argumento
   *buffer_callback*.

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

   Retorna la representación *pickle* del objeto *obj* como un objeto
   "bytes", en lugar de escribirlo en un archivo.

   Los argumentos *protocol*, *fix_imports* y *buffer_callback* tienen
   el mismo significado que en el constructor "Pickler".

   Distinto en la versión 3.8: Se agregó el argumento
   *buffer_callback*.

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

   Lee la representación *pickle* de un objeto desde un *archivo*
   abierto *file object* y retorna la jerarquía de objetos
   reconstituidos especificada en el mismo. Esto es equivalente a
   "Unpickler(file).load()".

   La versión de protocolo del *pickle* se detecta automáticamente,
   por lo que no se necesita ningún argumento de protocolo.  Los bytes
   más allá de la representación empaquetada son ignorados.

   Los argumentos *file*, *fix_imports*, *encoding*, *errors*,
   *strict* y *buffers* tienen el mismo significado que en el
   constructor "Unpickler".

   Distinto en la versión 3.8: Se agregó el argumento *buffers*.

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

   Retorna la jerarquía de objetos reconstruida de la representación
   *pickle* *data* de un objeto. *data* debe ser un objeto tipo
   binario (*bytes-like object*).

   La versión de protocolo del *pickle* se detecta automáticamente,
   por lo que no se necesita ningún argumento de protocolo.  Los bytes
   más allá de la representación empaquetada son ignorados.

   Los argumentos *fix_imports*, *encoding*, *errors*, *strict* y
   *buffers* tienen el mismo significado que en el constructor
   "Unpickler".

   Distinto en la versión 3.8: Se agregó el argumento *buffers*.

The "pickle" module defines three exceptions:

exception pickle.PickleError

   Common base class for the other pickling exceptions.  It inherits
   from "Exception".

exception pickle.PicklingError

   Error raised when an unpicklable object is encountered by
   "Pickler". It inherits from "PickleError".

   Consulte ¿Qué se puede serializar (pickled) y deserializar
   (unpickled) con pickle? para aprender qué tipos de objetos se
   pueden serializar con *pickle*.

exception pickle.UnpicklingError

   Error raised when there is a problem unpickling an object, such as
   a data corruption or a security violation.  It inherits from
   "PickleError".

   Tenga en cuenta que también se pueden generar otras excepciones
   durante la deserializacion con *pickle*, incluyendo (pero no
   necesariamente limitado a) *AttributeError*, *EOFError*,
   *ImportError*, e *IndexError*.

The "pickle" module exports three classes, "Pickler", "Unpickler" and
"PickleBuffer":

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

   Esto toma un archivo binario para escribir un flujo de datos de
   *pickle*.

   El argumento opcional *protocol* , un entero, le dice al *pickler*
   que use el protocolo dado; los protocolos admitidos son 0 para
   "HIGHEST_PROTOCOL". Si no se especifica, el valor predeterminado es
   "DEFAULT_PROTOCOL".  Si se especifica un número negativo,
   "HIGHEST_PROTOCOL" es seleccionado.

   El argumento *file* debe tener un método *write()* que acepte un
   argumento de bytes individuales.  Por lo tanto, puede ser un
   archivo en disco abierto para escritura binaria, una instancia
   "io.BytesIO" , o cualquier otro objeto personalizado que cumpla con
   esta interfaz.

   Si *fix_imports* es verdadero y *protocol* es menor que 3, *pickle*
   intentará asignar los nuevos nombres de Python 3 a los nombres de
   módulos antiguos utilizados en Python 2, de modo que la secuencia
   de datos de *pickle* sea legible con Python 2.

   If *buffer_callback* is "None" (the default), buffer views are
   serialized into *file* as part of the pickle stream.

   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 out-of-band;
   otherwise the buffer is serialized in-band, i.e. inside the pickle
   stream.

   It is an error if *buffer_callback* is not "None" and *protocol* is
   "None" or smaller than 5.

   Distinto en la versión 3.8: Se agregó el argumento
   *buffer_callback*.

   dump(obj)

      Escribe la representación serializada con *pickle* del objeto
      *obj* en el objeto archivo abierto dado en el constructor.

   persistent_id(obj)

      No hacer nada por defecto. Esto existe para que una subclase
      pueda sobreescribirlo.

      Si "persistent_id()" retorna "None", *obj* es serializado con
      *pickle* como siempre.  Cualquier otro valor hace que "Pickler"
      emita el valor retornado como un ID persistente para *obj*.  El
      significado de este ID persistente debe definirse por
      "Unpickler.persistent_load()".  Tenga en cuenta que el valor
      retornado por "persistent_id()" no puede tener una ID
      persistente.

      Ver Persistencia de objetos externos para detalles y ejemplos de
      uso.

      Distinto en la versión 3.13: Add the default implementation of
      this method in the C implementation of "Pickler".

   dispatch_table

      A pickler object's dispatch table is a registry of *reduction
      functions* of the kind which can be declared using
      "copyreg.pickle()".  It is a mapping whose keys are classes 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 "__reduce__()" method.

      Por defecto, un objeto de *pickle* no tendrá un atributo
      "dispatch_table", y en su lugar utilizará la tabla de despacho
      global administrada por el módulo "copyreg". Sin embargo, para
      personalizar el *pickling* para un objeto de *pickle*
      específico, se puede establecer el atributo "dispatch_table" en
      un objeto tipo dict.  Alternativamente, si una subclase de
      "Pickler" tiene un atributo "dispatch_table" esto se usará como
      la tabla de despacho predeterminada para instancias de esa
      clase.

      Ver Tablas de despacho para ejemplos de uso.

      Added in version 3.3.

   reducer_override(obj)

      Special reducer that can be defined in "Pickler" subclasses.
      This method has priority over any reducer in the
      "dispatch_table".  It should conform to the same interface as a
      "__reduce__()" method, and can optionally return
      "NotImplemented" to fallback on "dispatch_table"-registered
      reducers to pickle "obj".

      Para un ejemplo detallado, ver Reducción personalizada para
      tipos, funciones y otros objetos.

      Added in version 3.8.

   fast

      Obsoleto. Habilite el modo rápido si se establece en un valor
      verdadero. El modo rápido deshabilita el uso de memo, por lo
      tanto, acelera el proceso de *pickling* al no generar códigos de
      operación PUT superfluos. No debe usarse con objetos
      autorreferenciales; de lo contrario, la clase "Pickler" se
      repetirá infinitamente.

      Use "pickletools.optimize()" si necesita *pickles* más
      compactos.

   clear_memo()

      Clears the pickler's "memo".

      The memo is the data structure that remembers which objects the
      pickler has already seen, so that shared or recursive objects
      are pickled by reference and not by value.  This method is
      useful when re-using picklers.

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

   Esto toma un archivo binario para leer un flujo de datos de
   *pickle*.

   La versión de protocolo de *pickle* se detecta automáticamente, por
   lo que no se necesita ningún argumento de protocolo.

   El argumento *file* debe tener tres métodos, un método read() que
   toma un argumento entero, un método *readinto()* que toma un
   argumento búfer y un método *readline()* que no requiere
   argumentos, como en la interfaz "io.BufferedIOBase".  Por lo tanto
   *file* puede ser un archivo en disco abierto para lectura binaria,
   un objeto "io.BytesIO", o cualquier otro objeto personalizado que
   cumpla con esta interfaz.

   Los argumentos opcionales *fix_imports*, *encoding* and *errors* se
   utilizan para controlar el soporte de compatibilidad para el flujo
   de *pickle* generado por Python 2. Si *fix_imports* es verdadero,
   *pickle* intentará asignar los nombres antiguos de Python 2 a los
   nuevos nombres utilizados en Python 3.  Tanto *encoding* como
   *errors* le indican a *pickle* cómo decodificar instancias de
   cadenas de 8 bits seleccionadas por Python 2; estos son
   predeterminados a 'ASCII' y 'strict', respectivamente.  *encoding*
   puede ser 'bytes' para leer estas instancias de cadena de 8 bits
   como objetos de bytes. Se requiere el uso de "encoding='latin1'"
   para realizar el *unpickling* de arreglos de NumPy e instancias de
   "datetime", "date" y "time" serializados con *pickle* por Python 2.

   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 "Pickler" was
   instantiated (or when "dump()" or "dumps()" was called).

   If *buffers* is not "None", it should be an iterable of buffer-
   enabled objects that is consumed each time the pickle stream
   references an out-of-band buffer view.  Such buffers have been
   given in order to the *buffer_callback* of a Pickler object.

   Distinto en la versión 3.8: Se agregó el argumento *buffers*.

   load()

      Lee la representación serializada con *pickle* de un objeto
      desde el objeto de archivo abierto dado en el constructor, y
      retorne la jerarquía de objetos reconstituidos especificada
      allí.  Los Bytes más allá de la representación serializada con
      *pickle* del objeto se ignoran.

   persistent_load(pid)

      Lanza un "UnpicklingError" de forma predeterminada.

      Si se define, "persistent_load()" debería retornar el objeto
      especificado por el ID persistente *pid*.  Si se encuentra un ID
      persistente no válido, se debe lanzar un "UnpicklingError".

      Ver Persistencia de objetos externos para detalles y ejemplos de
      uso.

      Distinto en la versión 3.13: Add the default implementation of
      this method in the C implementation of "Unpickler".

   find_class(module, name)

      Importa *module* si es necesario y retorna el objeto llamado
      *name* desde el, donde los argumentos *module* y *name* son
      objetos de "str".  Tenga en cuenta que, a diferencia de lo que
      sugiere su nombre, "find_class()" también se usa para buscar
      funciones.

      Las subclases pueden sobreescribir esto para obtener control
      sobre qué tipo de objetos y cómo se pueden cargar, reduciendo
      potencialmente los riesgos de seguridad. Consulte Restricción de
      globals para obtener más detalles.

      Lanza un auditing event "pickle.find_class" con argumentos
      "module", "name".

class pickle.PickleBuffer(buffer)

   Un envoltorio (*wrapper*) para un búfer que representa datos
   serializables con *pickle* (*picklable data*).  *buffer* debe ser
   un objeto que proporciona un búfer (buffer-providing), como objeto
   tipo binario (*bytes-like object*) o un arreglo N-dimensional.

   "PickleBuffer" es en sí mismo un proveedor de búfer, por lo que es
   posible pasarlo a otras API que esperan un objeto que provea un
   búfer, como "memoryview".

   Los objetos "PickleBuffer" solo se pueden serializar usando el
   protocolo *pickle* 5 o superior.  Son elegibles para serialización
   fuera de banda (out-of-band serialization).

   Added in version 3.8.

   raw()

      Retorna un "memoryview" del área de memoria subyacente a este
      búfer. El objeto retornado es una vista de memoria
      unidimensional, C-contigua con formato "B" (bytes sin firmar).
      "BufferError" es lanzado si el búfer no es contiguo a C ni a
      Fortran.

   release()

      Libera el búfer subyacente expuesto por el objeto PickleBuffer.


¿Qué se puede serializar (pickled) y deserializar (unpickled) con *pickle*?
===========================================================================

Los siguientes tipos se pueden serializar con *pickle* (pickled):

* built-in constants ("None", "True", "False", "Ellipsis", and
  "NotImplemented");

* enteros, números de coma flotante, números complejos;

* cadenas de caracteres, bytes, bytearrays;

* tuplas, listas, conjuntos y diccionarios que contienen solo objetos
  serializables con pickle;

* funciones (incorporadas y definidas por el usuario) accesibles desde
  el nivel superior de un módulo (usando "def", no "lambda")

* clases accesibles desde el nivel superior de un módulo;

* instances of such classes for which the result of calling
  "__getstate__()" is picklable  (see section Pickling de Instancias
  de clases for details).

Los intentos de serializar objetos no serializables con *pickle*
lanzaran la excepción "PicklingError"; cuando esto sucede, es posible
que ya se haya escrito una cantidad no especificada de bytes en el
archivo subyacente.  Intentar serializar con *pickle* una estructura
de datos altamente recursiva puede exceder la profundidad máxima de
recursividad, en este caso se lanzará  un "RecursionError".  Puede
aumentar cuidadosamente este límite con "sys.setrecursionlimit()".

Tenga en cuenta que las funciones (integradas y definidas por el
usuario) están completamente serializadas con *pickle* por *qualified
name*, no por valor. [2] Esto significa que solo se serializa el
nombre de la función, junto con el nombre del módulo y las clases que
lo contienen. No se serializa ni el código de la función ni ninguno de
sus atributos de función. Por lo tanto, el módulo de definición debe
poder importarse en el entorno de deserialización y el módulo debe
contener el objeto nombrado; de lo contrario, se generará una
excepción. [3]

De manera similar, las clases se serializan por nombre completo, por
lo que se aplican las mismas restricciones en el entorno de
deserialización. Tenga en cuenta que ninguno de los códigos o datos de
la clase se serializa, por lo que en el siguiente ejemplo, el atributo
de clase "attr" no se restaura en el entorno de deserializado:

   class Foo:
       attr = 'A class attribute'

   picklestring = pickle.dumps(Foo)

Estas restricciones son la razón por la que las funciones y clases
serializables con pickle deben definirse en el nivel superior de un
módulo.

Similarly, when class instances are pickled, their class's code and
data are not 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 "__setstate__()" method.


*Pickling* de Instancias de clases
==================================

En esta sección, describimos los mecanismos generales disponibles para
que usted defina, personalice y controle cómo se serializan y
deserializan con *Pickle* las instancias de clase.

In most cases, no additional code is needed to make instances
picklable.  By default, pickle will retrieve the class and the
attributes of an instance via introspection. When a class instance is
unpickled, its "__init__()" 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:

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

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

Las clases pueden alterar el comportamiento predeterminado
proporcionando uno o varios métodos especiales:

object.__getnewargs_ex__()

   In protocols 2 and newer, classes that implement the
   "__getnewargs_ex__()" method can dictate the values passed to the
   "__new__()" method upon unpickling.  The method must return a pair
   "(args, kwargs)" 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 "__new__()" method upon
   unpickling.

   Debes implementar este método si el método "__new__()" de tu clase
   requiere argumentos de solo palabras clave.  De lo contrario, se
   recomienda para la compatibilidad implementar "__getnewargs__()".

   Distinto en la versión 3.6: "__getnewargs_ex__()" ahora se usa en
   los protocolos 2 y 3.

object.__getnewargs__()

   Este método tiene un propósito similar a "__getnewargs_ex__()",
   pero solo admite argumentos posicionales.  Debe retornar una tupla
   de argumentos "args" que se pasarán al método "__new__()" al hacer
   *unpickling*.

   "__getnewargs__()" no se llamará si "__getnewargs_ex__()" está
   definido.

   Distinto en la versión 3.6: Antes de Python 3.6, se llamaba a,
   "__getnewargs__()" en lugar de "__getnewargs_ex__()" en los
   protocolos 2 y 3.

object.__getstate__()

   Las clases pueden influir aún más en cómo se serializan con
   *pickle* sus instancias sobrescribiendo el método "__getstate__()".
   Se llama y el objeto devuelto se conserva como el contenido de la
   instancia, en lugar de un estado predeterminado. Hay varios casos:

   * Para una clase que no tiene instancias "__dict__" ni "__slots__",
     el estado predeterminado es "None".

   * Para una clase que tiene una instancia "__dict__" y no tiene
     "__slots__", el estado predeterminado es "self.__dict__".

   * Para una clase que tiene una instancia "__dict__" y "__slots__",
     el estado predeterminado es una tupla que consta de dos
     diccionarios: "self.__dict__" y un diccionario que asigna nombres
     de ranura a valores de ranura. Solo las ranuras que tienen un
     valor se incluyen en este último.

   * Para una clase que tiene "__slots__" y ninguna instancia
     "__dict__", el estado predeterminado es una tupla cuyo primer
     elemento es "None" y cuyo segundo elemento es un diccionario que
     asigna nombres de ranura a valores de ranura descritos en la
     viñeta anterior.

   Distinto en la versión 3.11: Se agregó la implementación
   predeterminada del método "__getstate__()" en la clase "object".

object.__setstate__(state)

   Al hacer *unpickling*, si la clase define "__setstate__()", este es
   llamado con el estado *unpickled* (no serializado con *pickle*).
   En ese caso, no es necesario que el objeto de estado sea un
   diccionario.  De lo contrario, el estado *pickled* (*pickled
   state*) debe ser un diccionario y sus elementos se asignan al
   diccionario de la nueva instancia.

   Nota:

     If "__reduce__()" returns a state with value "None" at pickling,
     the "__setstate__()" method will not be called upon unpickling.

Refer to the section Manejo de objetos con estado for more information
about how to use the methods "__getstate__()" and "__setstate__()".

Nota:

  At unpickling time, some methods like "__getattr__()",
  "__getattribute__()", or "__setattr__()" may be called upon the
  instance.  In case those methods rely on some internal invariant
  being true, the type should implement "__new__()" to establish such
  an invariant, as "__init__()" is not called when unpickling an
  instance.

As we shall see, pickle does not use directly the methods described
above.  In fact, these methods are part of the copy protocol which
implements the "__reduce__()" special method.  The copy protocol
provides a unified interface for retrieving the data necessary for
pickling and copying objects. [4]

Although powerful, implementing "__reduce__()" directly in your
classes is error prone.  For this reason, class designers should use
the high-level interface (i.e., "__getnewargs_ex__()",
"__getstate__()" and "__setstate__()") whenever possible.  We will
show, however, cases where using "__reduce__()" is the only option or
leads to more efficient pickling or both.

object.__reduce__()

   La interfaz se define actualmente de la siguiente manera. El método
   "__reduce__()" no toma ningún argumento y retornará una cadena o
   preferiblemente una tupla (el objeto retornado a menudo se denomina
   "valor reducido").

   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: for a given "obj" to be
   pickled, the "__module__" attribute is looked up on "obj" directly,
   which falls back to a lookup on the type of "obj" if no
   "__module__" instance attribute is set. This behaviour is typically
   useful for singletons.

   Cuando se retorna una tupla, debe tener entre dos y seis elementos.
   Los elementos opcionales se pueden omitir o se puede proporcionar
   "None" como su valor.  La semántica de cada elemento está en orden:

   * Un objeto invocable que se llamará para crear la versión inicial
     del objeto.

   * Una tupla de argumentos para el objeto invocable. Se debe
     proporcionar una tupla vacía si el invocable no acepta ningún
     argumento.

   * Opcionalmente, el estado del objeto, que se pasará al método
     "__setstate__()" del objeto como se describió anteriormente. Si
     el objeto no tiene dicho método, el valor debe ser un diccionario
     y se agregará al atributo "__dict__" del objeto.

   * Optionally, an iterator (and not a sequence) yielding successive
     items. These items will be appended to the object either using
     "obj.append(item)" or, in batch, using
     "obj.extend(list_of_items)". This is primarily used for list
     subclasses, but may be used by other classes as long as they have
     "append()" and "extend()" methods with the appropriate signature.
     (Whether "append()" or "extend()" is used depends on which pickle
     protocol version is used as well as the number of items to
     append, so both must be supported.)

   * Opcionalmente, un iterador (no una secuencia) que produce pares
     clave-valor sucesivos.  Estos elementos se almacenarán en el
     objeto usando "obj[key] = value".  Esto se usa principalmente
     para subclases de diccionario, pero otras clases pueden usarlo
     siempre que implementen "__setitem__()".

   * Opcionalmente, un invocable con una firma "(obj, state)". Este
     invocable permite al usuario controlar programáticamente el
     comportamiento de actualización de estado de un objeto
     específico, en lugar de usar el método estático de "obj"
     "__setstate__()". Si no es "None", este invocable tendrá
     prioridad sobre "obj"'s "__setstate__()".

     Added in version 3.8: Se agregó el sexto elemento opcional de
     tupla "(obj, state)".

object.__reduce_ex__(protocol)

   Alternativamente, se puede definir un método "__reduce_ex__()".  La
   única diferencia es que este método debe tomar un único argumento
   entero, la versión del protocolo.  Cuando esté definido, *pickle*
   lo preferirá en lugar del método "__reduce__()".  Además,
   "__reduce__()" se convierte automáticamente en sinónimo de la
   versión extendida.  El uso principal de este método es proporcionar
   valores reducidos compatibles con versiones anteriores para
   versiones anteriores de Python.


Persistencia de objetos externos
--------------------------------

For the benefit of object persistence, the "pickle" module supports
the 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) [5] or
just an arbitrary object (for any newer protocol).

The resolution of such persistent IDs is not defined by the "pickle"
module; it will delegate this resolution to the user-defined methods
on the pickler and unpickler, "persistent_id()" and
"persistent_load()" respectively.

Para seleccionar objetos que tienen una ID persistente externo, el
*pickler* debe tener un método personalizado "persistent_id()" que
toma un objeto como argumento y retorna "None" o el ID persistente
para ese objeto. Cuando se retorna "None", el *pickler* simplemente
serializará el objeto de forma normal. Cuando se retorna una cadena de
identificación persistente, el *pickler* serializará ese objeto, junto
con un marcador para que el *unpickler* lo reconozca como una
identificación persistente.

Para hacer el *unpickling* objetos externos, el *unpickler* debe tener
un método personalizado "persistent_load()" que toma un objeto de
identificación persistente y retorna el objeto referenciado.

Aquí hay un ejemplo completo que presenta cómo se puede usar la
identificación persistente para hacer el *pickling* objetos externos
por referencia.

   # 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()


Tablas de despacho
------------------

Si se desea personalizar el *pickling* de algunas clases sin alterar
ningún otro código que dependa del *pickling*, se puede crear un
*pickler* con una tabla de despacho privada.

The global dispatch table managed by the "copyreg" module is available
as "copyreg.dispatch_table".  Therefore, one may choose to use a
modified copy of "copyreg.dispatch_table" as a private dispatch table.

Por ejemplo

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

crea una instancia de "pickle.Pickler" con una tabla de despacho
privada que maneja la clase "AlgunaClase" especialmente.
Alternativamente, el código

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

hace lo mismo, pero todas las instancias de "MyPickler" compartirán de
forma predeterminada la tabla de despacho privada. Por otro lado, el
código

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

modifica la tabla de despacho global compartida por todos los usuarios
del módulo "copyreg".


Manejo de objetos con estado
----------------------------

Here's an example that shows how to modify pickling behavior for a
class. The "TextReader" class below opens a text file, and returns the
line number and line contents each time its "readline()" method is
called. If a "TextReader" 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
"__setstate__()" and "__getstate__()" methods are used to implement
this behavior.

   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

Un ejemplo de uso podría ser algo como esto:

   >>> 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!'


Reducción personalizada para tipos, funciones y otros objetos
=============================================================

Added in version 3.8.

A veces, "dispatch_table" puede no ser lo suficientemente flexible. En
particular, es posible que deseemos personalizar el *pickling* en
función de otro criterio que no sea el tipo de objeto, o es posible
que deseemos personalizar el *pickling* de funciones y clases.

For those cases, it is possible to subclass from the "Pickler" class
and implement a "reducer_override()" method. This method can return an
arbitrary reduction tuple (see "__reduce__()"). It can alternatively
return "NotImplemented" to fallback to the traditional behavior.

Si se definen tanto "dispatch_table" como "reducer_override()",
entonces "reducer_override()" tiene prioridad.

Nota:

  Por motivos de rendimiento, no se puede llamar a
  "reducer_override()" para los siguientes objetos: "None", "True",
  "False", e instancias exactas de "int", "float", "bytes", "str",
  "dict", "set", "frozenset", "list" y "tuple".

Aquí hay un ejemplo simple donde permitimos el *pickling* y
reconstruir una clase dada class:

   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


Búferes fuera de banda
======================

Added in version 3.8.

In some contexts, the "pickle" module is used to transfer massive
amounts 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 "pickle" 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.

Esta restricción puede evitarse si tanto el *proveedor* (la
implementación de los tipos de objeto a transferir) como el
*consumidor* (a implementación del sistema de comunicaciones) admiten
las facilidades de transferencia fuera de banda proporcionadas por el
protocolo *pickle* 5 y mayor.


API de proveedor
----------------

The large data objects to be pickled must implement a
"__reduce_ex__()" method specialized for protocol 5 and higher, which
returns a "PickleBuffer" instance (instead of e.g. a "bytes" object)
for any large data.

A "PickleBuffer" object *signals* that the underlying buffer is
eligible for out-of-band data transfer.  Those objects remain
compatible with normal usage of the "pickle" module.  However,
consumers can also opt-in to tell "pickle" that they will handle those
buffers by themselves.


API de consumidor
-----------------

Un sistema de comunicaciones puede permitir el manejo personalizado de
los objetos "PickleBuffer" generados al serializar un gráfico de
objetos.

En el lado del envío, necesita pasar un argumento *buffer_callback* a
"Pickler" (o a las funciones "dump()" o "dumps()"), que se llamará con
cada "PickleBuffer" generado al hacer *pickling* del gráfico del
objeto.  Los búferes acumulados por *buffer_callback* no verán sus
datos copiados en el flujo de *pickle*, solo se insertará un marcador
barato.

En el lado receptor, necesita pasar un argumento *buffers* a
"Unpickler" (o a las funciones "load()" o "loads()"), que es un
iterable de los búferes que fueron pasado a *buffer_callback*. Ese
iterable debería producir búferes en el mismo orden en que se pasaron
a *buffer_callback*.   Esos búferes proporcionarán los datos esperados
por los reconstructores de los objetos cuyo *pickling* produjo los
objetos originales "PickleBuffer".

Entre el lado de envío y el lado de recepción, el sistema de
comunicaciones es libre de implementar su propio mecanismo de
transferencia para memorias intermedias fuera de banda. Las posibles
optimizaciones incluyen el uso de memoria compartida o compresión
dependiente del tipo de datos.


Ejemplo
-------

Aquí hay un ejemplo trivial donde implementamos una subclase
"bytearray" capaz de participar en el *pickling* de un búfer fuera de
banda:

   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)

El reconstructor (el método de clase "_reconstruct") retorna el objeto
que proporciona el búfer si tiene el tipo correcto.  Esta es una
manera fácil de simular el comportamiento de copia cero en este
ejemplo de juguete.

En el lado del consumidor, podemos serializar con *pickle* esos
objetos de la forma habitual, que cuando no se serializan nos dará una
copia del objeto original:

   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

Pero si pasamos un *buffer_callback* y luego retornamos los búferes
acumulados al anular la serialización, podemos recuperar el objeto
original:

   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

Este ejemplo está limitado por el hecho de que "bytearray" asigna su
propia memoria: no puedes crear una instancia de "bytearray" que esté
respaldada por la memoria de otro objeto.  Sin embargo, los tipos de
datos de terceros, como las matrices NumPy no tienen esta limitación y
permiten el uso de *pickling* de copia cero (o realizar la menor
cantidad de copias posible) cuando se transfieren entre procesos o
sistemas distintos.

Ver también:

  **PEP 574** -- Protocolo Pickle 5 con datos fuera de banda


Restricción de globals
======================

De forma predeterminada, el *unpickling* importará cualquier clase o
función que encuentre en los datos de *pickle*.  Para muchas
aplicaciones, este comportamiento es inaceptable, ya que permite al
*unpickler* importar e invocar código arbitrario.  Solo considere lo
que hace este flujo de datos de *pickle* hechos a mano cuando se
carga:

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

En este ejemplo, el *unpickler* importa la función "os.system()" y
luego aplica el argumento de cadena *"echo hello world"*.  Aunque este
ejemplo es inofensivo, no es difícil imaginar uno que pueda dañar su
sistema.

Por esta razón, es posible que desee controlar lo que se deserializa
con *pickle* personalizando "Unpickler.find_class()".  A diferencia de
lo que sugiere su nombre, "Unpickler.find_class()" se llama siempre
que se solicita un global (es decir, una clase o una función).  Por lo
tanto, es posible prohibir completamente los globales o restringirlos
a un subconjunto seguro.

Aquí hay un ejemplo de un *unpickler* que permite cargar solo unas
pocas clases seguras del módulo "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()

Un ejemplo de uso de nuestro deserializador que funciona según lo
previsto:

   >>> 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

Como muestran nuestros ejemplos, debes tener cuidado con lo que
permites que se deserialize con *pickle*.  Por lo tanto, si la
seguridad es un problema, puede considerar alternativas como la API de
*marshalling* en "xmlrpc.client" o soluciones de terceros.


Performance
===========

Recent versions of the pickle protocol (from protocol 2 and upwards)
feature efficient binary encodings for several common features and
built-in types. Also, the "pickle" module has a transparent optimizer
written in C.


Ejemplos
========

Para obtener el código más simple, use las funciones "dump()" y
"load()".

   import pickle

   # An arbitrary collection of objects supported by pickle.
   data = {
       'a': [1, 2.0, 3+4j],
       '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)

El siguiente ejemplo lee los datos serializados con *pickle*
resultantes.

   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)


Command-line interface
======================

The "pickle" module can be invoked as a script from the command line,
it will display contents of the pickle files. However, when the pickle
file that you want to examine comes from an untrusted source, "-m
pickletools" is a safer option because it does not execute pickle
bytecode, see pickletools CLI usage.

   python -m pickle pickle_file [pickle_file ...]

The following option is accepted:

pickle_file

   A pickle file to read, or "-" to indicate reading from standard
   input.

Ver también:

  Módulo "copyreg"
     Registro de constructor de interfaz *Pickle* para tipos de
     extensión.

  Módulo "pickletools"
     Herramientas para trabajar y analizar datos serializados con
     *pickle*.

  Módulo "shelve"
     Indexed databases of objects; uses "pickle".

  Módulo "copy"
     Copia de objetos superficial y profunda.

  Módulo "marshal"
     Serialización de alto rendimiento de tipos integrados.

-[ Notas al pie ]-

[1] No confunda esto con el módulo "marshal"

[2] Esta es la razón por la que las funciones "lambda" no se pueden
    serializar con *pickle*:  todas las funciones "lambda" comparten
    el mismo nombre:  "<lambda>".

[3] La excepción generada probablemente será un "ImportError" o un
    "AttributeError" pero podría ser otra cosa.

[4] El módulo "copy" utiliza este protocolo para operaciones de copia
    superficial y profunda.

[5] La limitación de caracteres alfanuméricos se debe a que los ID
    persistentes en el protocolo 0 están delimitados por el carácter
    de nueva línea. Por lo tanto, si se produce algún tipo de carácter
    de nueva línea en los ID persistentes, los datos serializados
    resultantes se volverán ilegibles.
