"pickle" --- Serialização de objetos Python
*******************************************

**Código-fonte:** 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".

Aviso:

  O módulo "pickle" **não é seguro**. Desserialize com pickle apenas
  os dados em que você confia.É possível construir dados maliciosos em
  pickle que irão **executar código arbitrário durante o processo de
  desserialização com pickle**. Nunca desserialize com pickle os dados
  que possam vir de uma fonte não confiável ou que possam ter sido
  adulterados.Considere assinar dados com "hmac" se você precisar
  garantir que eles não foram adulterados.Formatos de serialização
  mais seguros como "json" podem ser mais apropriados se você estiver
  processando dados não confiáveis. Vejo Comparação com json.


Relacionamento com outros módulos Python
========================================


Comparação com "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.


Comparação com "json"
---------------------

Existem diferenças fundamentais entre os protocolos pickle e JSON
(JavaScript Object Notation):

* JSON é um formato de serialização de texto (ele produz texto
  unicode, embora na maioria das vezes seja codificado para "utf-8"),
  enquanto pickle é um formato de serialização binário;

* JSON é legível por humanos, enquanto pickle não é;

* JSON é interoperável e amplamente usado fora do ecossistema Python,
  enquanto pickle é específico para Python;

* JSON, por padrão, só pode representar um subconjunto dos tipos
  embutidos do Python, e nenhuma classe personalizada; pickle pode
  representar um número extremamente grande de tipos Python (muitos
  deles automaticamente, pelo uso inteligente dos recursos de
  introspecção do Python; casos complexos podem ser resolvidos
  implementando APIs de objetos específicos);

* Ao contrário do pickle, a desserialização não confiável do JSON não
  cria, por si só, uma vulnerabilidade de execução de código
  arbitrário.

Ver também:

  O módulo "json": um módulo de biblioteca padrão que permite a
  serialização e desserialização JSON.


Formato de fluxo de dados
=========================

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.

Existem atualmente 6 protocolos diferentes que podem ser usados para a
serialização com pickle. Quanto mais alto o protocolo usado, mais
recente é a versão do Python necessária para ler o pickle produzido.

* A versão 0 do protocolo é o protocolo original "legível por humanos"
  e é compatível com versões anteriores do Python.

* A versão 1 do protocolo é um formato binário antigo que também é
  compatível com versões anteriores do Python.

* A versão 2 do protocolo foi introduzida no Python 2.3. Ela fornece
  uma serialização com pickle muito mais eficiente de *classes estilo
  novo*. Consulte **PEP 307** para obter informações sobre as
  melhorias trazidas pelo protocolo 2.

* A versão 3 do protocolo foi adicionada ao Python 3.0. Ela tem
  suporte explícito a objetos "bytes" e não é possível desserializar
  com pickle a partir do Python 2.x. Este era o protocolo padrão no
  Python 3.0--3.7.

* A versão 4 do protocolo foi adicionada ao Python 3.4. Ela adiciona
  suporte para objetos muito grandes, serialização com pickle de mais
  tipos de objetos e algumas otimizações de formato de dados. Isso é o
  protocolo padrão no Python 3.8--3.13. Consulte **PEP 3154** para
  obter informações sobre as melhorias trazidas pelo protocolo 4.

* A versão 5 do protocolo foi adicionada ao Python 3.8. Ela adiciona
  suporte a dados fora da banda e aumento de velocidade para dados
  dentro da banda. É o protocolo padrão a partir do Python 3.14.
  Consulte **PEP 574** para obter informações sobre as melhorias
  trazidas pelo protocolo 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.


Interface do módulo
===================

Para serializar uma hierarquia de objeto, você simplesmente chama a
função "dumps()". Da mesma forma, para desserializar um fluxo de
dados, você chama a função "loads()". No entanto, se você quiser mais
controle sobre a serialização e desserialização, pode criar um objeto
"Pickler" ou "Unpickler", respectivamente.

The "pickle" module provides the following constants:

pickle.HIGHEST_PROTOCOL

   Um inteiro, a mais alta versão de protocolo disponível. Este valor
   pode ser passado como um valor de *protocol* para as funções
   "dump()" e "dumps()", bem como o construtor de "Pickler".

pickle.DEFAULT_PROTOCOL

   Um inteiro, a versão de protocolo padrão usada para a serialização
   com pickle. Pode ser menor que "HIGHEST_PROTOCOL". Atualmente, o
   protocolo padrão é 5, introduzido pela primeira vez no Python 3.8 e
   incompatível com as versões anteriores. Esta versão introduz
   suporte para buffers fora da banda, nos quais dados compatíveis com
   **PEP 3118** podem ser transmitidos separadamente do fluxo
   principal do pickle.

   Alterado na versão 3.0: O protocolo padrão é 3.

   Alterado na versão 3.8: O protocolo padrão é 4.

   Alterado na versão 3.14: O protocolo padrão é o 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)

   Escreve a representação após a serialização com pickle do objeto
   *obj* no *objeto arquivo* aberto *file*. Isso é equivalente a
   "Pickler(file, protocol).dump(obj)".

   Os argumentos *file*, *protocol*, *fix_imports* e *buffer_callback*
   têm o mesmo sentido que no construtor de "Pickler".

   Alterado na versão 3.8: O argumento *buffer_callback* foi
   adicionado.

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

   Retorna a representação em após a serialização com pickle do objeto
   *obj* como um objeto "bytes", ao invés de escrevê-lo em um arquivo.

   Os argumentos *protocol*, *fix_imports* e *buffer_callback* têm o
   mesmo sentido que no construtor de "Pickler".

   Alterado na versão 3.8: O argumento *buffer_callback* foi
   adicionado.

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

   Lê a representação serializada com pickle de um objeto a partir de
   *objeto arquivo* aberto *file* e retorna a hierarquia de objeto
   reconstituído especificada nele. Isso é equivalente a
   "Unpickler(file).load()".

   A versão do protocolo pickle é detectada automaticamente, portanto,
   nenhum argumento de protocolo é necessário. Bytes após a
   representação serializada com pickle do objeto são ignorados.

   Os argumentos *file*, *fix_imports*, *encoding*, *errors*, *strict*
   e *buffers* têm o mesmo significado que no construtor construtor
   "Unpickler".

   Alterado na versão 3.8: O argumento *buffers* foi adicionado.

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

   Retorna a hierarquia de objeto reconstituído da representação
   serializada com pickle *data* de um objeto. *data* deve ser um
   *objeto bytes ou similar*.

   A versão do protocolo pickle é detectada automaticamente, portanto,
   nenhum argumento de protocolo é necessário. Bytes após a
   representação serializada com pickle do objeto são ignorados.

   Os argumentos *fix_imports*, *encoding*, *errors*, *strict* e
   *buffers* têm o mesmo significado que no construtor construtor
   "Unpickler".

   Alterado na versão 3.8: O argumento *buffers* foi adicionado.

The "pickle" module defines three exceptions:

exception pickle.PickleError

   Classe base comum para as outras exceções de serialização com
   pickle. Herda de "Exception".

exception pickle.PicklingError

   Erro levantado quando um objeto não serializável com pickle é
   encontrado por "Pickler". Herda de "PickleError".

   Consulte O que pode ser serializado e desserializado com pickle?
   para saber quais tipos de objetos podem ser serializados com
   pickle.

exception pickle.UnpicklingError

   Erro levantado quando há um problema ao desserializar com pickle um
   objeto, como dados corrompidos ou violação de segurança. Herda de
   "PickleError".

   Observe que outras exceções também podem ser levantadas durante a
   desserialização com pickle, incluindo (mas não necessariamente
   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)

   Isso leva um arquivo binário a escrever um fluxo de dados pickle.

   O argumento opcional *protocol*, um inteiro, diz ao pickler para
   usar o protocolo fornecido; os protocolos suportados são de 0 a
   "HIGHEST_PROTOCOL". Se não for especificado, o padrão é
   "DEFAULT_PROTOCOL". Se um número negativo for especificado,
   "HIGHEST_PROTOCOL" é selecionado.

   O argumento *file* deve ter um método write() que aceite um
   argumento de um único byte. Portanto, pode ser um arquivo em disco
   aberto para escrita binária, uma instância "io.BytesIO" ou qualquer
   outro objeto personalizado que atenda a esta interface.

   Se *fix_imports* for verdadeiro e *protocolo* for menor que 3,
   pickle tentará mapear os novos nomes do Python 3 para os nomes dos
   módulos antigos usados no Python 2, de modo que o fluxo de dados
   pickle seja legível com o Python 2.

   Se *buffer_callback* for "None" (o padrão), as visualizações de
   buffer são serializadas em *file* como parte do fluxo pickle.

   Se *buffer_callback* não for "None", ele pode ser chamado qualquer
   número de vezes com uma visualização de buffer. Se essa chamada
   retornar um valor falso (tal como "None"), o buffer fornecido é
   fora da banda; caso contrário, o buffer é serializado dentro da
   banda, ou seja, dentro do fluxo pickle.

   É um erro se *buffer_callback* não for "None" e *protocol* for
   "None" ou menor que 5.

   Alterado na versão 3.8: O argumento *buffer_callback* foi
   adicionado.

   dump(obj)

      Escreve a representação serializada em pickle de *obj* no objeto
      arquivo aberto fornecido no construtor.

   persistent_id(obj)

      Não faz nada por padrão. Isso existe para que uma subclasse
      possa substituí-lo.

      Se "persistent_id()" retornar "None", *obj* é serializado com
      pickle como de costume. Qualquer outro valor faz com que
      "Pickler" emita o valor retornado como um ID persistente para
      *obj*. O significado deste ID persistente deve ser definido por
      "Unpickler.persistent_load()". Observe que o valor retornado por
      "persistent_id()" não pode ter um ID persistente.

      Consulte Persistência de objetos externos para detalhes e
      exemplos de usos.

      Alterado na versão 3.13: Foi adicionada a implementação padrão
      desse método na implementação em C da "Pickler".

   dispatch_table

      A tabela de despacho de um objeto pickler é um registro de
      *funções de redução* do tipo que pode ser declarado usando
      "copyreg.pickle()". É um mapeamento cujas chaves são classes e
      cujos valores são funções de redução. Uma função de redução leva
      um único argumento da classe associada e deve estar de acordo
      com a mesma interface de um método "__reduce__()".

      Por padrão, um objeto pickler não terá um atributo
      "dispatch_table", e em vez disso usará a tabela de despacho
      global gerenciada pelo módulo "copyreg". No entanto, para
      personalizar a serialização com pickle de um objeto pickler
      específico, pode-se definir o atributo "dispatch_table" para um
      objeto do tipo dict. Alternativamente, se uma subclasse de
      "Pickler" tem um atributo "dispatch_table" então ele será usado
      como a tabela de despacho padrão para instâncias daquela classe.

      Consulte Tabelas de despacho para exemplos de uso.

      Adicionado na versão 3.3.

   reducer_override(obj)

      Redutor especial que pode ser definido em subclasses de
      "Pickler". Este método tem prioridade sobre qualquer redutor em
      "dispatch_table". Ele deve estar de acordo com a mesma interface
      que um método "__reduce__()" e pode opcionalmente retornar
      "NotImplemented" como alternativa em redutores registrados em
      "dispatch_table" para serializar com pickle "obj".

      Para exemplo detalhado, consulte Redução personalizada para
      tipos, funções e outros objetos.

      Adicionado na versão 3.8.

   fast

      Descontinuado. Ative o modo rápido se definido como um valor
      verdadeiro. O modo rápido desabilita o uso de memo, portanto,
      agilizando o processo de serialização com pickle por não gerar
      códigos de operação PUT supérfluos. Ele não deve ser usado com
      objetos autorreferenciais, fazer o contrário fará com que
      "Pickler" recorra infinitamente.

      Use "pickletools.optimize()" se você precisar de serializações
      com pickle mais compactas.

   clear_memo()

      Limpa o "memo" do pickler

      O memo é a estrutura de dados que lembra quais objetos o pickler
      já viu, de modo que objetos compartilhados ou recursivos sejam
      serializados por pickle por referência e não por valor. Este
      método é útil ao reutilizar picklers.

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

   Recebe um arquivo binário para ler um fluxo de dados pickle.

   A versão do protocolo do pickle é detectada automaticamente,
   portanto, nenhum argumento de protocolo é necessário.

   O argumento *file* deve ter três métodos: um método read() que
   recebe um argumento inteiro, um método readinto() que recebe um
   argumento buffer e um método readline() que não requer argumentos,
   como na interface "io.BufferedIOBase". Assim, *file* pode ser um
   arquivo em disco aberto para leitura binária, um objeto
   "io.BytesIO" ou qualquer outro objeto personalizado que atenda a
   esta interface.

   Os argumentos opcionais *fix_imports*, *encoding* e *errors* são
   usados para controlar o suporte de compatibilidade ao fluxo pickle
   gerado pelo Python 2. Se *fix_imports* for verdadeiro, pickle
   tentará mapear os nomes antigos do Python 2 para os novos nomes
   usados no Python 3. Os *encoding* e *erros* dizem ao pickle como
   decodificar instâncias de string de 8 bits capturadas pelo Python
   2; o padrão é 'ASCII' e 'strict', respectivamente. O argumento
   *encoding* pode ser 'bytes' para ler essas instâncias de string de
   8 bits como objetos de bytes. Usar "encoding='latin1'" é necessário
   para a desserialização com pickle de vetores NumPy e instâncias de
   "datetime", "date" e "time" serializadas com pickle pelo Python 2.

   Se *buffers* for "None" (o padrão), todos os dados necessários para
   desserialização devem estar contidos no fluxo pickle. Isso
   significa que o argumento *buffer_callback* era "None" quando um
   "Pickler" foi instanciado (ou quando "dump()" ou "dumps()" foi
   chamado).

   Se *buffers* for "None", deve ser um iterável de objetos
   habilitados para buffer que é consumido cada vez que o fluxo de
   serialização com pickle faz referência a uma visualização de buffer
   fora da banda. Esses buffers foram fornecidos em ordem para o
   *buffer_callback* de um objeto Pickler.

   Alterado na versão 3.8: O argumento *buffers* foi adicionado.

   load()

      Lê a representação serializada com pickle de um objeto a partir
      do objeto arquivo aberto fornecido no construtor e retorna a
      hierarquia de objeto reconstituído especificada nele. Os bytes
      após a representação serializada com pickle do objeto são
      ignorados.

   persistent_load(pid)

      Levanta um "UnpicklingError" por padrão.

      Se definido, "persistent_load()" deve retornar o objeto
      especificado pelo ID persistente *pid*. Se um ID persistente
      inválido for encontrado, uma "UnpicklingError" deve ser
      levantada.

      Consulte Persistência de objetos externos para detalhes e
      exemplos de usos.

      Alterado na versão 3.13: Foi adicionada a implementação padrão
      desse método na implementação em C da "Unpickler".

   find_class(module, name)

      Importa *module* se necessário e retorna o objeto chamado *name*
      dele, onde os argumentos *module* e *name* são objetos "str".
      Observe, ao contrário do que seu nome sugere, "find_class()"
      também é usado para encontrar funções.

      As subclasses podem substituir isso para obter controle sobre
      quais tipos de objetos e como eles podem ser carregados,
      reduzindo potencialmente os riscos de segurança. Confira
      Restringindo globais para detalhes.

      Levanta um evento de auditoria "pickle.find_class" com os
      argumentos "module", "name".

class pickle.PickleBuffer(buffer)

   Um invólucro para um buffer que representa dados serializáveis com
   pickle. *buffer* deve ser um objeto provedor de buffer, como um
   *objeto bytes ou similar* ou um vetor N-dimensional.

   "PickleBuffer" é ele próprio um provedor de buffer, de forma que é
   possível passá-lo para outras APIs que esperam um objeto provedor
   de buffer, como "memoryview".

   Objetos "PickleBuffer" só podem ser serializados usando o protocolo
   pickle 5 ou superior. Eles são elegíveis para serialização fora de
   banda.

   Adicionado na versão 3.8.

   raw()

      Retorna um "memoryview" da área de memória subjacente a este
      buffer. O objeto retornado é um memoryview unidimensional,
      contíguo C com formato "B" (bytes não assinados). "BufferError"
      é levantada se o buffer não for contíguo C nem Fortran.

   release()

      Libera o buffer subjacente exposto pelo objeto PickleBuffer.


O que pode ser serializado e desserializado com pickle?
=======================================================

Os seguintes tipos podem ser serializados com pickle:

* constantes embutidas ("None", "True", "False", "Ellipsis" e
  "NotImplemented");

* inteiros, números de ponto flutuante, números complexos;

* strings, bytes, bytearrays;

* tuplas, listas, conjuntos e dicionários contendo apenas objetos
  serializáveis com pickle;

* funções (embutidas ou definidas pelo usuário) acessíveis no nível
  superior de um módulo (usando "def", não "lambda");

* classes acessíveis no nível superior de um módulo;

* instances of such classes for which the result of calling
  "__getstate__()" is picklable  (see section Serializando com pickle
  instâncias de classes for details).

As tentativas de serializar objetos não serializáveis com pickle vão
levantar a exceção "PicklingError"; quando isso acontece, um número
não especificado de bytes pode já ter sido escrito no arquivo
subjacente. Tentar serializar com pickle uma estrutura de dados
altamente recursiva pode exceder a profundidade máxima de recursão, a
"RecursionError" será levantada neste caso. Você pode aumentar este
limite cuidadosamente com "sys.setrecursionlimit()".

Observe que as funções (embutidas e definidas pelo usuário) são
serializadas com pickle pelo *nome qualificado*, não pelo valor. [2]
Isso significa que apenas o nome da função é serializado com pickle,
junto com o nome do módulo e das classes contidos. Nem o código da
função, nem qualquer um de seus atributos de função são serializados
com pickle. Assim, o módulo de definição deve ser importável no
ambiente de desserialização com pickle, e o módulo deve conter o
objeto nomeado, caso contrário, uma exceção será levantada. [3]

Da mesma forma, as classes são serializadas com pickle pelo nome
qualificado, portanto, aplicam-se as mesmas restrições no ambiente de
desserialização com pickle. Observe que nenhum código ou dado da
classe é coletado, portanto, no exemplo a seguir, o atributo de classe
"attr" não é restaurado no ambiente de desserialização com pickle:

   class Foo:
       attr = 'A class attribute'

   picklestring = pickle.dumps(Foo)

Essas restrições são a razão pela qual as funções e classes
serializáveis com pickle devem ser definidas no nível superior de um
módulo.

Da mesma forma, quando as instâncias da classe são serializadas com
pickle, o código e os dados de sua classe não são serializados junto
com elas. Apenas os dados da instância são serializados com pickle.
Isso é feito de propósito para que você possa corrigir bugs em uma
classe ou adicionar métodos à classe e ainda carregar objetos que
foram criados com uma versão anterior da classe. Se você planeja ter
objetos de longa duração que verão muitas versões de uma classe, pode
valer a pena colocar um número de versão nos objetos para que as
conversões adequadas possam ser feitas pelo método "__setstate__()" da
classe.


Serializando com pickle instâncias de classes
=============================================

Nesta seção, descrevemos os mecanismos gerais disponíveis para você
definir, personalizar e controlar como as instâncias de classe são
serializadas e desserializadas com pickle.

Na maioria dos casos, nenhum código adicional é necessário para tornar
as instâncias serializáveis com pickle. Por padrão, o pickle
recuperará a classe e os atributos de uma instância por meio de
introspecção. Quando uma instância de classe não está serializada com
pickle, seu método "__init__()" geralmente *não* é invocado. O
comportamento padrão primeiro cria uma instância não inicializada e,
em seguida, restaura os atributos salvos. O código a seguir mostra uma
implementação desse comportamento:

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

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

As classes podem alterar o comportamento padrão, fornecendo um ou
vários métodos especiais:

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.

   Você deve implementar este método se o método "__new__()" de sua
   classe requer argumentos somente-nomeados. Caso contrário, é
   recomendado para compatibilidade implementar "__getnewargs__()".

   Alterado na versão 3.6: "__getnewargs_ex__()" é agora usado em
   protocolos 2 e 3.

object.__getnewargs__()

   Este método serve a um propósito semelhante ao de
   "__getnewargs_ex__()", mas tem suporte apenas a argumentos
   posicionais. Ele deve retornar uma tupla de argumentos "args" que
   serão passados para o método "__new__()" após a desserialização com
   pickle.

   "__getnewargs__()" não será chamado se "__getnewargs_ex__()"
   estiver definido.

   Alterado na versão 3.6: Antes do Python 3.6, "__getnewargs__()" era
   chamado em vez de "__getnewargs_ex__()" nos protocolos 2 e 3.

object.__getstate__()

   Classes podem influenciar ainda mais como suas instâncias são
   serializadas com pickle, substituindo o método "__getstate__()".
   Ele é chamado e o objeto retornado é serializado com pickle como o
   conteúdo da instância, em vez de um estado padrão. Existem vários
   casos:

   * Para uma classe que não possui instância "__dict__" e não possui
     "__slots__", o estado padrão é "None".

   * Para uma classe que não uma possui instância "__dict__" nem
     "__slots__", o estado padrão é "self.__dict__".

   * Para uma classe que possui uma instância "__dict__" e
     "__slots__", o estado padrão é uma tupla consistindo de dois
     dicionários: "self.__dict__", e um dicionário de mapeamento de
     nomes de slot para valores de slot. Apenas os slots que possuem
     um valor são incluídos neste último.

   * Para uma classe que possui "__slots__" e nenhuma "__dict__" de
     instância, o estado padrão é uma tupla cujo primeiro item é
     "None" e cujo segundo item é um dicionário mapeando os nomes dos
     slots para os valores dos slots descritos no tópico anterior.

   Alterado na versão 3.11: Adicionada a implementação padrão do
   método "__getstate__()" na classe "objeto".

object.__setstate__(state)

   Ao desserializar com pickle, se a classe define "__setstate__()",
   ela é chamada com o estado não desserializado. Nesse caso, não há
   nenhum requisito para que o objeto de estado seja um dicionário.
   Caso contrário, o estado serializado com pickle deve ser um
   dicionário e seus itens são atribuídos ao dicionário da nova
   instância.

   Nota:

     Se "__reduce__()" retorna um estado com valor "None" na
     serialização com pickle, o método "__setstate__()" não será
     chamado quando da desserialização com pickle.

Confira a seção Manipulação de objetos com estado para mais
informações sobre como usar os métodos "__getstate__()" e
"__setstate__()".

Nota:

  Quando da desserialização com pickle, alguns métodos, como
  "__getattr__()", "__getattribute__()" ou "__setattr__()", podem ser
  chamados na instância. No caso desses métodos dependerem de alguma
  invariante interna ser verdadeira, o tipo deve ser implementado
  "__new__()" para estabelecer tal invariante, pois "__init__()" não é
  chamada quando da desserialização com pickle em uma instância.

Como veremos, o pickle não usa diretamente os métodos descritos acima.
Na verdade, esses métodos são parte do protocolo de cópia que
implementa o método especial "__reduce__()". O protocolo de cópia
fornece uma interface unificada para recuperar os dados necessários
para serialização com pickle e cópia de objetos. [4]

Apesar de poderoso, implementar "__reduce__()" diretamente em sua
classe é algo propenso a erro. Por este motivo, designers de classe
devem usar a interface de alto nível (ou seja, "__getnewargs_ex__()",
"__getstate__()" e "__setstate__()") sempre que possível. Vamos
mostrar, porém, casos em que o uso de "__reduce__()" é a única opção
ou leva a uma serialização com pickle mais eficiente, ou as ambas.

object.__reduce__()

   A interface está atualmente definida da seguinte maneira. O método
   "__reduce__()" não aceita nenhum argumento e deve retornar uma
   string ou preferencialmente uma tupla (o objeto retornado é
   frequentemente referido como o "valor de redução").

   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.

   Quando uma tupla é retornada, ela deve ter entre dois e seis itens.
   Os itens opcionais podem ser omitidos ou "None" pode ser fornecido
   como seu valor. A semântica de cada item está em ordem:

   * Um objeto chamável que será chamado para criar a versão inicial
     do objeto.

   * Uma tupla de argumentos para o objeto chamável. Uma tupla vazia
     deve ser fornecida se o chamável não aceitar nenhum argumento.

   * Opcionalmente, o estado do objeto, que será passado para o método
     "__setstate__()" do objeto conforme descrito anteriormente. Se o
     objeto não tiver tal método, o valor deve ser um dicionário e
     será adicionado ao atributo "__dict__" do objeto.

   * Opcionalmente, um iterador (e não uma sequência) produzindo itens
     sucessivos. Esses itens serão anexados ao objeto usando
     "obj.append(item)" ou, em lote, usando
     "obj.extend(list_of_items)". Isso é usado principalmente para
     subclasses de lista, mas pode ser usado por outras classes, desde
     que tenham os métodos "append()" e "extend()" com a assinatura
     apropriada. (Se "append()" ou "extend()" é usado depende de qual
     versão do protocolo pickle é usada, bem como o número de itens a
     anexar, então ambos devem ser suportados.)

   * Opcionalmente, um iterador (não uma sequência) produzindo pares
     de valor-chave sucessivos. Esses itens serão armazenados no
     objeto usando "obj[chave]=valor". Isso é usado principalmente
     para subclasses de dicionário, mas pode ser usado por outras
     classes, desde que implementem "__setitem__()".

   * Opcionalmente, um chamável com uma assinatura "(obj, estado)".
     Este chamável permite ao usuário controlar programaticamente o
     comportamento de atualização de estado de um objeto específico,
     ao invés de usar o método estático "__setstate__()" de "obj". Se
     não for "None", este chamável terá prioridade sobre o
     "__setstate__()" de "obj".

     Adicionado na versão 3.8: O sexto item opcional de tupla, "(obj,
     estado)", foi adicionado.

object.__reduce_ex__(protocol)

   Alternativamente, um método "__reduce_ex__()" pode ser definido. A
   única diferença é que este método deve ter um único argumento
   inteiro, a versão do protocolo. Quando definido, pickle irá
   preferir isso ao método "__reduce__()". Além disso, "__reduce__()"
   automaticamente se torna um sinônimo para a versão estendida. O
   principal uso desse método é fornecer valores de redução com
   compatibilidade reversa para versões mais antigas do Python.


Persistência 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 serializar com pickle objetos que têm um ID externo persistente,
o pickler deve ter um método "persistent_id()" personalizado que
recebe um objeto como um argumento e retorna "None" ou o ID
persistente para esse objeto. Quando "None" é retornado, o pickler
simplesmente serializa o objeto normalmente. Quando uma string de ID
persistente é retornada, o pickler serializa aquele objeto, junto com
um marcador para que o unpickler o reconheça como um ID persistente.

Para desserializar com pickle objetos externos, o unpickler deve ter
um método "persistent_load()" personalizado que recebe um objeto de ID
persistente e retorna o objeto referenciado.

Aqui está um exemplo abrangente que apresenta como o ID persistente
pode ser usado para serializar com pickle objetos externos por
referência.

   # Exemplo simples que mostra como o ID persistente pode ser usado
   # serializar com pickle objetos externos por referência.

   import pickle
   import sqlite3
   from collections import namedtuple

   # Classe simples que representa um registro em nosso banco de dados.
   MemoRecord = namedtuple("MemoRecord", "key, task")

   class DBPickler(pickle.Pickler):

       def persistent_id(self, obj):
           # Em vez de conservar MemoRecord como uma instância de classe regular,
           # emitimos um ID persistente.
           if isinstance(obj, MemoRecord):
               # Aqui, nosso ID persistente é simplesmente uma tupla, contendo
               # uma tag e uma chave, que se refere a um registro específico
               # no banco de dados.
               return ("MemoRecord", obj.key)
           else:
               # Se obj não tiver um ID persistente, retorna None. Significa que
               # obj precisa ser conservado como de costume.
               return None


   class DBUnpickler(pickle.Unpickler):

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

       def persistent_load(self, pid):
           # Este método é invocado sempre que um ID persistente é encontrado.
           # Aqui, pid é a tupla retornada por DBPickler.
           cursor = self.connection.cursor()
           type_tag, key_id = pid
           if type_tag == "MemoRecord":
               # Busca o registro referenciado no banco de dados e retorna-o.
               cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),))
               key, task = cursor.fetchone()
               return MemoRecord(key, task)
           else:
               # Sempre levanta um erro se você puder retornar o objeto correto.
               # Caso contrário, a desserialização com pickle considerará que
               # None é o objeto referenciado pelo ID persistente.
               raise pickle.UnpicklingError("unsupported persistent object")


   def main():
       import io
       import pprint

       # Inicializa e popula nosso banco de dados.
       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,))

       # Busca os registros a serem serializados com pickle.
       cursor.execute("SELECT * FROM memos")
       memos = [MemoRecord(key, task) for key, task in cursor]
       # Salva os registros usando nosso DBPickler personalizado.
       file = io.BytesIO()
       DBPickler(file).dump(memos)

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

       # Atualiza um registro, só por precaução.
       cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1")

       # Carrega os registros do fluxo de dados pickle.
       file.seek(0)
       memos = DBUnpickler(file, conn).load()

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


   if __name__ == '__main__':
       main()


Tabelas de despacho
-------------------

Se alguém quiser personalizar a serialização com pickle de algumas
classes sem perturbar nenhum outro código que dependa da serialização,
pode-se criar um pickler com uma tabela de despacho privada.

A tabela de despacho global gerenciada pelo módulo "copyreg" está
disponível como "copyreg.dispatch_table". Portanto, pode-se escolher
usar uma cópia modificada de "copyreg.dispatch_table" como uma tabela
de despacho privada.

Por exemplo

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

cria uma instância de "pickle.Pickler" com uma tabela de despacho
privada que trata a classe "SomeClass" especialmente.
Alternativamente, o código

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

faz o mesmo, mas todas as instâncias de "MyPickler" compartilharão por
padrão a tabela de despacho privada. Por outro lado, o código

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

modifica a tabela de despacho global compartilhada por todos os
usuários do módulo "copyreg".


Manipulação de objetos com estado
---------------------------------

Aqui está um exemplo que mostra como modificar o comportamento de
serialização com pickle de uma classe. A classe "TextReader" abaixo
abre um arquivo texto e retorna o número da linha e o conteúdo da
linha cada vez que seu método "readline()" é chamado. Se uma instância
de "TextReader" for selecionada, todos os atributos *exceto* o membro
do objeto arquivo são salvos. Quando a instância é removida, o arquivo
é reaberto e a leitura continua a partir do último local. Os métodos
"__setstate__()" e "__getstate__()" são usados para implementar este
comportamento.

   class TextReader:
       """Exibe e numera linhas em um arquivo texto."""

       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):
           # Copia o estado do objeto de self.__dict__, que
           # contém todos os nossos atributos de instância.
           # Sempre use o método dict.copy() para evitar
           # modificar o estado original.
           state = self.__dict__.copy()
           # Remove as entradas não serializáveis com pickle.
           del state['file']
           return state

       def __setstate__(self, state):
           # Restaura os atributos da instância (isto é, filename e lineno).
           self.__dict__.update(state)
           # Restaura o estado do arquivo aberto anteriormente.
           # Para fazer isso, precisamos reabri-lo e ler dele até
           # a contagem de linha ser restaurada.
           file = open(self.filename)
           for _ in range(self.lineno):
               file.readline()
           # Ao final, salva o arquivo.
           self.file = file

Um exemplo de uso pode ser algo assim:

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


Redução personalizada para tipos, funções e outros objetos
==========================================================

Adicionado na versão 3.8.

Às vezes, "dispatch_table" pode não ser flexível o suficiente. Em
particular, podemos querer personalizar a serialização com pickle com
base em outro critério que não o tipo do objeto, ou podemos
personalizar a serialização com pickle de funções e classes.

Para esses casos, é possível criar uma subclasse da classe "Pickler" e
implementar um método "reducer_override()". Este método pode retornar
uma tupla de redução arbitrária (veja "__reduce__()"). Ele pode,
alternativamente, retornar "NotImplemented" para retornar ao
comportamento tradicional.

Se "dispatch_table" e "reducer_override()" forem definidos, o método
"reducer_override()" tem prioridade.

Nota:

  Por motivos de desempenho, "reducer_override()" não pode ser chamado
  para os seguintes objetos: "None", "True", "False", e as instâncias
  exatas de "int", "float", "bytes", "str", "dict", "set",
  "frozenset", "list" e "tuple".

Aqui está um exemplo simples onde permitimos serialização com pickle e
reconstrução de uma determinada classe:

   import io
   import pickle

   class MyClass:
       my_attribute = 1

   class MyPickler(pickle.Pickler):
       def reducer_override(self, obj):
           """Redutor personalizado para MyClass."""
           if getattr(obj, "__name__", None) == "MyClass":
               return type, (obj.__name__, obj.__bases__,
                             {'my_attribute': obj.my_attribute})
           else:
               # Para qualquer outro objeto, recorre à redução de costume
               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


Buffers fora da banda
=====================

Adicionado na versão 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 restrição pode ser evitada se tanto o *fornecedor* (a
implementação dos tipos de objetos a serem transferidos) e o
*consumidor* (a implementação do sistema de comunicações) tiverem
suporte aos recursos de transferência fora de banda fornecidos pelo
protocolo pickle 5 e superior.


API de provedor
---------------

Os grandes objetos de dados a serem serializados com pickle devem
implementar um método "__reduce_ex__()" especializado para o protocolo
5 e superior, que retorna uma instância "PickleBuffer" (em vez de, por
exemplo, um objeto "bytes") para quaisquer dados grandes.

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

Um sistema de comunicação pode permitir o manuseio personalizado dos
objetos "PickleBuffer" gerados ao serializar um grafo de objeto.

No lado emissor, é necessário passar um argumento *buffer_callback*
para "Pickler" (ou para a função "dump()" ou "dumps()"), que será
chamada com cada "PickleBuffer" gerado durante a serialização com
pickle do grafo do objeto. Os buffers acumulados pelo
*buffer_callback* não verão seus dados copiados no fluxo pickle,
apenas um marcador barato será inserido.

No lado receptor, é necessário passar um argumento *buffers* para
"Unpickler" (ou para a função "load()" ou "load()"), que é um iterável
dos buffers que foram passado para *buffer_callback*. Esse iterável
deve produzir buffers na mesma ordem em que foram passados para
*buffer_callback*. Esses buffers fornecerão os dados esperados pelos
reconstrutores dos objetos cuja serialização com pickle produziu os
objetos "PickleBuffer" originais.

Entre o lado emissor e o lado receptor, o sistema de comunicações está
livre para implementar seu próprio mecanismo de transferência para
buffers fora de banda. As otimizações potenciais incluem o uso de
memória compartilhada ou compactação dependente do tipo de dados.


Exemplo
-------

Aqui está um exemplo trivial onde implementamos uma subclasse de
"bytearray" capaz de participar de serialização com pickle de buffer
fora de banda:

   class ZeroCopyByteArray(bytearray):

       def __reduce_ex__(self, protocol):
           if protocol >= 5:
               return type(self)._reconstruct, (PickleBuffer(self),), None
           else:
               # PickleBuffer é proibido no pickle nos protocolos <= 4.
               return type(self)._reconstruct, (bytearray(self),)

       @classmethod
       def _reconstruct(cls, obj):
           with memoryview(obj) as m:
               # Obtém um controle sobre o objeto buffer original
               obj = m.obj
               if type(obj) is cls:
                   # O objeto do buffer original é um ZeroCopyByteArray,
                   # retorna-o como está.
                   return obj
               else:
                   return cls(obj)

O reconstrutor (o método de classe "_reconstruct") retorna o objeto de
fornecimento do buffer se ele tiver o tipo correto. Esta é uma maneira
fácil de simular o comportamento de cópia zero neste exemplo de
brinquedo.

Do lado consumidor, podemos serializar com pickle esses objetos da
maneira usual, que quando não serializados nos dará uma cópia do
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: uma cópia foi feita

Mas se passarmos um *buffer_callback* e, em seguida, retornarmos os
buffers acumulados ao desserializar, seremos capazes de recuperar o
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: nenhuma cópia foi feita

Este exemplo é limitado pelo fato de que "bytearray" aloca sua própria
memória: você não pode criar uma instância de "bytearray" que é
apoiada pela memória de outro objeto. No entanto, tipos de dados de
terceiros, como arrays de NumPy, não têm essa limitação e permitem o
uso de serialização com pickle de cópia zero (ou fazer o mínimo de
cópias possível) ao transferir entre processos ou sistemas distintos.

Ver também:

  **PEP 574** -- Protocolo de Pickle 5 com buffers de dados fora da
  banda


Restringindo globais
====================

Por padrão, a desserialização com pickle importará qualquer classe ou
função que encontrar nos dados pickle. Para muitos aplicativos, esse
comportamento é inaceitável, pois permite que o unpickler importe e
invoque código arbitrário. Basta considerar o que este fluxo de dados
pickle feito à mão faz quando carregado:

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

Neste exemplo, o unpickler importa a função "os.system()" e então
aplica o argumento string "echo hello world". Embora este exemplo seja
inofensivo, não é difícil imaginar um que possa danificar seu sistema.

Por esta razão, você pode querer controlar o que é desserializado com
pickle personalizando "Unpickler.find_class()". Ao contrário do que
seu nome sugere, "Unpickler.find_class()" é chamado sempre que um
global (ou seja, uma classe ou uma função) é solicitado. Assim, é
possível proibir completamente os globais ou restringi-los a um
subconjunto seguro.

Aqui está um exemplo de um unpickler que permite que apenas algumas
classes seguras do módulo "builtins" sejam carregadas:

   import builtins
   import io
   import pickle

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

   class RestrictedUnpickler(pickle.Unpickler):

       def find_class(self, module, name):
           # Só permite classes seguras de bultins.
           if module == "builtins" and name in safe_builtins:
               return getattr(builtins, name)
           # Proíbe todo o resto.
           raise pickle.UnpicklingError("global '%s.%s' is forbidden" %
                                        (module, name))

   def restricted_loads(s):
       """Função auxiliar análoga a pickle.loads()."""
       return RestrictedUnpickler(io.BytesIO(s)).load()

Um exemplo de uso do nosso unpickler funcionando como esperado:

   >>> 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 nossos exemplos mostram, você deve ter cuidado com o que permite
que seja desserializado com pickle. Portanto, se a segurança é uma
preocupação, você pode querer considerar alternativas como a API de
marshalling em "xmlrpc.client" ou soluções de terceiros.


Desempenho
==========

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.


Exemplos
========

Para código mais simples, use as funções "dump()" e "load()".

   import pickle

   # Uma coleção arbitrária de objetos aceitos por 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:
       # Serializa com pickle o dicionário 'data' usando
       # o protocolo mais alto disponível.
       pickle.dump(data, f, pickle.HIGHEST_PROTOCOL)

O exemplo a seguir lê os dados resultantes em serializados com pickle.

   import pickle

   with open('data.pickle', 'rb') as f:
       # A versão do protocolo utilizada é detectada automaticamente,
       # portanto não precisamos especificá-la.
       data = pickle.load(f)


Interface de linha de comando
=============================

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 aquivo_pickle [aquivo_pickle ...]

A seguinte opção é aceita:

pickle_file

   Um arquivo pickle para ler, ou "-" para indicar leitura da entrada
   padrão.

Ver também:

  Módulo "copyreg"
     Registro de construtor de interface Pickle para tipos de
     extensão.

  Módulo "pickletools"
     Ferramentas para trabalhar e analisar dados serializados com
     pickle.

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

  Módulo "copy"
     Cópia rasa e cópia profunda de objeto.

  Módulo "marshal"
     Serialização de alto desempenho de tipos embutidos.

-[ Notas de rodapé ]-

[1] Não confunda isso com o módulo "marshal"

[2] É por isso que funções "lambda" não podem ser serializadas com
    pickle: todas as funções "lambda" compartilham o mesmo nome:
    "<lambda>".

[3] A exceção levantada provavelmente será uma "ImportError" ou uma
    "AttributeError", mas poderia ser outra coisa.

[4] O módulo "copy" usa este protocolo para operações de cópia rasa e
    cópia profunda.

[5] A limitação de caracteres alfanuméricos se deve ao fato de que os
    IDs persistentes, no protocolo 0, serem delimitados pelo caractere
    de nova linha. Portanto, se qualquer tipo de caractere de nova
    linha ocorrer em IDs persistentes, os dados resultantes da
    serialização com pickle se tornarão ilegíveis.
