Serializar datos usando los módulos pickle y cPickle

La serialización es un proceso de almacenamiento de un objeto como un flujo de bytes o caracteres para transmitirlo a través de una red o almacenarlo en el disco para recrearlo junto con su estado cuando sea necesario. El proceso inverso se llama deserialización. 

En Python, el módulo Pickle nos proporciona los medios para serializar y deserializar los objetos de Python. Pickle es una biblioteca poderosa que puede serializar muchos objetos complejos y personalizados que otras bibliotecas no pueden hacer. Al igual que pickle, hay un módulo cPickle que comparte los mismos métodos que pickle, pero está escrito en C. El módulo cPickle está escrito como una función de C en lugar de un formato de clase.

Diferencia entre Pickle y cPickle:

  • Pickle usa una implementación basada en la clase de python, mientras que cPickle está escrito como funciones C. Como resultado, cPickle es muchas veces más rápido que pickle.
  • Pickle está disponible tanto en python 2.x como en python 3.x, mientras que cPickle está disponible en python 2.x de manera predeterminada. Para usar cPickle en python 3.x, podemos importar _pickle.
  • cPickle no admite la subclase de pickle. cPickle es mejor si la subclasificación no es importante; de ​​lo contrario, Pickle es la mejor opción.

Dado que tanto pickle como cPickle comparten la misma interfaz, podemos usar ambos de la misma manera. A continuación se muestra un código de ejemplo como referencia:

Python3

try:
    
    # In python 2.x it is available as default
    import cPickle as pickle
except ImportError:
    
    # In python 3.x cPickle is not available
    import pickle
  
import random
  
# A custom class to demonstrate pickling 
class ModelTrainer:
    def __init__(self) -> None:
        self.weights = [0,0,0]
      
    def train(self):
        for i in range(len(self.weights)):
            self.weights[i] = random.random()
      
    def get_weights(self):
        return self.weights
  
# Create an object 
model = ModelTrainer()
  
# Populate the data
model.train()
  
print('Weights before pickling', model.get_weights())
  
# Open a file to write bytes
p_file = open('model.pkl', 'wb')
  
# Pickle the object
pickle.dump(model, p_file)
p_file.close()
  
# Deserialization of the file
file = open('model.pkl','rb')
new_model = pickle.load(file)
  
print('Weights after pickling', new_model.get_weights())

Producción:

Pesos antes del decapado [0,6089721131909885, 0,7891019431265203, 0,5653418337976294]

Pesos después del decapado [0,6089721131909885, 0,7891019431265203, 0,5653418337976294]

En el código anterior, hemos creado una clase personalizada ModelTrainer que inicializa una lista de 0. El método train() llena la lista con algunos valores aleatorios y el método get_weight() devuelve los valores generados. A continuación, creamos el objeto modelo e imprimimos los pesos generados. Hemos creado un nuevo archivo en modo ‘wb’ (Escribir bytes). El método dump() volcó el objeto como flujo de bytes en el archivo. La verificación se realiza cargando el archivo en un nuevo objeto e imprimiendo los pesos.

El módulo Pickle es muy poderoso para los objetos de Python. Pero solo puede preservar los datos, no la estructura de clases. Por lo tanto, cualquier objeto de clase personalizado no se cargará si no proporcionamos la definición de clase. A continuación se muestra un ejemplo cuando falla el decapado:

Python3

try:
    # In python 2.x it is available as default
    import cPickle as pickle
except ImportError:
    
    # In python 3.x cPickle is not available
    import pickle
  
# Deserialization of the file
file = open('model.pkl','rb')
new_model = pickle.load(file)
  
print('Weights of model', new_model.get_weights())

Producción:

Rastreo (llamadas recientes más última):

 Archivo “des.py”, línea 12, en <módulo>

   nuevo_modelo = pickle.load(archivo)

AttributeError: no se puede obtener el atributo ‘ModelTrainer’ en <módulo ‘__main__’ de ‘des.py’>

El error anterior se generó porque nuestro script actual no conoce la clase de este objeto. Por lo tanto, podemos decir que pickle solo conserva los datos dentro del objeto, pero no puede guardar los métodos y la estructura de clases.

Para rectificar el error anterior, debemos proporcionar la definición de clase al script. A continuación se muestra un ejemplo de cómo cargar correctamente objetos personalizados:

Python3

try:
    
    # In python 2.x it is available as default
    import cPickle as pickle
except ImportError:
    
    # In python 3.x cPickle is not available
    import pickle
  
import random
  
# If the file is available,
# we can use import statement to import the class
  
# A custom class to demonstrate pickling
class ModelTrainer:
    def __init__(self) -> None:
        self.weights = [0, 0, 0]
  
    def train(self):
        for i in range(len(self.weights)):
            self.weights[i] = random.random()
  
    def get_weights(self):
        return self.weights
  
# Deserialization of the file
file = open('model.pkl', 'rb')
new_model = pickle.load(file)
  
print('Weights of model', new_model.get_weights())

Producción:

Pesos del modelo [0.6089721131909885, 0.7891019431265203, 0.5653418337976294]

Hemos proporcionado una referencia para la clase ModelTrainer. El script ahora reconoce la clase y puede volver a llamar al constructor para construir el objeto. En lugar de escribir todo el código de la clase, simplemente podemos importarlo desde el archivo anterior.

Serialización como string

También podemos serializar un objeto como una string. Los módulos Pickle y cPickle proporcionan métodos dumps() y loads(). El método dumps() toma el objeto como parámetro y devuelve la string codificada. El método load() hace lo contrario. Toma la string codificada y devuelve el objeto original. A continuación se muestra el código para serializar un objeto personalizado como una string.

Python3

try:
    
    # In python 2.x it is available as default
    import cPickle as pickle
except ImportError:
    
    # In python 3.x cPickle is not available
    import pickle
  
import random
  
# A custom class to demonstrate pickling 
class ModelTrainer:
    def __init__(self) -> None:
        self.weights = [0,0,0]
      
    def train(self):
        for i in range(len(self.weights)):
            self.weights[i] = random.random()
      
    def get_weights(self):
        return self.weights
  
# Create an object 
model = ModelTrainer()
  
# Populate the data
model.train()
  
print('Weights before pickling', model.get_weights())
  
# Pickle the object
byte_string = pickle.dumps(model)
  
print("The bytes of object are:",byte_string)
  
# Deserialization of the object using same byte string
new_model = pickle.loads(byte_string)
  
print('Weights after depickling', new_model.get_weights())

Producción:

Pesos antes del decapado [0,923474126606742, 0,34909608824193983, 0,3761122243447367]

Los bytes del objeto son: b’\x80\x03c__main__\nModelTrainer\nq\x00)\x81q\x01}q\x02X\x07\x00\x00\x00weightsq\x03]q\x04(G?\xed\x8d\x19 \x9c\x8fL\xc3G?\xd6W\x97\x1e\x8aHHG?\xd8\x129\x01\xcb\xee\xf2esb.’

Pesos después del decapado [0,923474126606742, 0,34909608824193983, 0,3761122243447367]

Publicación traducida automáticamente

Artículo escrito por mukulbindal170299 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *