Almacenamiento de datos II. Serialización
¿Que es la serialización?
La serialización consiste en el almacenamiento en un fichero externo una colección, diccionario o un objeto en código binario. Dentro de las múltiples ventajas que ofrece guardar un archivo en código binario se encuentra la facilidad que ofrece este formato para ser distribuido por internet, para ser almacenado en un dispositivo de almacenamiento externo, o si se desea almacenar en una base de datos.
Para poder guardar objetos en formato binario es necesario usar la biblioteca de Python Pickle, la cual contiene entre otros, el método .DUMP() que permite hacer un volcado de datos al fichero binario externo y el método .LOAD() que permite cargar los datos binarios almacenados en el fichero externo.
Veamos el siguiente ejemplo:
import os
os.system('cls')
import pickle
lNombres = ['Carlos', 'José', 'César', 'Luis']
archivo_binario=open('lista_nombres.bin','wb')
pickle.dump(lNombres,archivo_binario)
archivo_binario.close
del (archivo_binario)
archivo_binario2 = open('lista_nombres.bin','rb')
lNombres2 = pickle.load(archivo_binario2)
print(lNombres2)
Resultado:
['Carlos', 'José', 'César', 'Luis']
Como podemos observar hemos hecho uso de la biblioteca PICKLE para acceder a datos de archivos binarios. El método open funciona igual que en el caso del móduo IO excepto que para leer y escribir datos en formato binarios es necesario utilizar el parámetro "WB" (write bytes) para escritura en binario o "RB" (read bytes) para lectura en binario. Otro punto destacable en el código anterior es el uso de la instrucción DEL cuyo propósito es el de destruir o eliminar objetos.
Su sintaxis es tan simple como la ´palabra reservada DEL (del inglés delete que significa borrar) seguido del nombre del objeto: DEL <objeto a eliminar>.
Veamos un ejemplo del uso de archivos externos para almacenar objetos, para ello vamos a recuperar los objetos vehículos vistos en el apartado de clases y objetos en Python. Consideremos el siguiente código:
import os
os.system('cls')
import pickle
class vehiculos():
def __init__(self,marca,modelo) -> None:
self.marca=marca
self.modelo=modelo
self.color="Blanco"
self.detenido=True
self.acelerando=False
self.frenando=False
def acelerar(self):
self.detenido=False
self.acelerando=True
self.frenando=False
def frenar(self):
self.detenido=True
self.acelerando=False
self.frenando=True
def estado(self):
print(f'''
**************************************************************************************
** Status del Vehículo
** Marca.......................{self.marca}
** Modelo......................{self.modelo}
** Color.......................{self.color}
** Acelerando..................{self.acelerando}
** Frenando....................{self.frenando}
** Detenido....................{self.detenido}
**
**************************************************************************************
''')
auto01=vehiculos('Ford','Fiesta')
# auto01.estado()
auto02=vehiculos('Chevrolet','Chevette')
# auto02.estado()
auto03=vehiculos('Fiat','Fiorino')
# auto03.estado()
print('Vehículos creados ok')
lista_autos=[auto01,auto02,auto03]
archivo_binario = open('automoviles.bin','wb')
print('Archivo binario creado ok')
pickle.dump(lista_autos,archivo_binario)
print('Volcado de datos en archivo binario ok')
archivo_binario.close
del archivo_binario
print('Cerrado de archivo binario ok')
Resultado:
Vehículos creados ok
Archivo binario creado ok
Volcado de datos en archivo binario ok
Cerrado de archivo binario ok
Como podemos ver el programa ha volcado data a un archivo binario a través del método .DUMP() de la clase PICKLE el cual vierte el contenido de cualquier objeto en Python dentro de un archivo binario, creado previamente con el método OPEN() con el parámetro 'wb' para que utilice formato binario en la creación del archivo.
Ahora bien, este archivo llamado automoviles.bin puede ser abierto desde otro programa en Python, solo que si no contiene las definiciones de clases de los objetos, no va a poder utilizar dichos objetos ya que arrojaría error. Veamos el siguiente ejemplo en otro archivo distinto pero ubicado en el mismo directorio que el archivo binario "automoviles.bin":
import os
os.system('cls')
import pickle
vehiculos_bin=open('automoviles.bin','rb')
print('Archivo binario abierto ok')
lista_vehiculos = pickle.load(vehiculos_bin)
print('Data binaria cargada ok')
vehiculos_bin.close()
print('Archivo binario cerrado ok')
print('El contenido del archivo binario es:')
for i in lista_vehiculos:
print(i)
Resultado:
Archivo binario abierto ok
Traceback (most recent call last):
File "e:\Documentos\Desarrollos\Python\Curso-Python\19.1 Objetos serializados 2.py", line 10, in <module>
lista_vehiculos = pickle.load(vehiculos_bin)
^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: Can't get attribute 'vehiculos' on <module '__main__' from 'e:\\Documentos\\Desarrollos\\Python\\Curso-Python\\19.1 Objetos serializados 2.py'>
Como podemos comprobar el programa se ejecuta correctamente hasta que intenta cargar los objetos en formato binario dentro de la lista_vehiculos. Esto sucede por que en este nuevo código no están definidas las clases de los objetos que se estan importando. Esto se puede solucionar declarando previamente las clases que se vayan a utilizar. Veamos como quedaría el código:
import os
os.system('cls')
import pickle
class vehiculos():
def __init__(self,marca,modelo) -> None:
self.marca=marca
self.modelo=modelo
self.color="Blanco"
self.detenido=True
self.acelerando=False
self.frenando=False
def acelerar(self):
self.detenido=False
self.acelerando=True
self.frenando=False
def frenar(self):
self.detenido=True
self.acelerando=False
self.frenando=True
def estado(self):
print(f'''
**************************************************************************************
** Status del Vehículo
** Marca.......................{self.marca}
** Modelo......................{self.modelo}
** Color.......................{self.color}
** Acelerando..................{self.acelerando}
** Frenando....................{self.frenando}
** Detenido....................{self.detenido}
**
**************************************************************************************
''')
vehiculos_bin=open('automoviles.bin','rb')
print('Archivo binario abierto ok')
lista_vehiculos = pickle.load(vehiculos_bin)
print('Data binaria cargada ok')
vehiculos_bin.close()
print('Archivo binario cerrado ok')
print('El contenido del archivo binario es:')
for i in lista_vehiculos:
print(i)
Resultado:
Archivo binario abierto ok
Data binaria cargada ok
Archivo binario cerrado ok
El contenido del archivo binario es:
<__main__.vehiculos object at 0x000001B5B4ED8610>
<__main__.vehiculos object at 0x000001B5B4EF1DD0>
<__main__.vehiculos object at 0x000001B5B4EF1E50>
Podemos comprobar como ahora Python si entiende la naturaleza de la data binaria que esta leyendo y puede proceder a manipular los objetos correctamente. De hecho en el bucle FOR podemos ver como se muestran las direcciones de memoria de los objetos contenidos en la lista. Ahora si podemos acceder a las propiedades y métodos de los objetos de la lista:
import os
os.system('cls')
import pickle
class vehiculos():
def __init__(self,marca,modelo) -> None:
self.marca=marca
self.modelo=modelo
self.color="Blanco"
self.detenido=True
self.acelerando=False
self.frenando=False
def acelerar(self):
self.detenido=False
self.acelerando=True
self.frenando=False
def frenar(self):
self.detenido=True
self.acelerando=False
self.frenando=True
def estado(self):
print(f'''
**************************************************************************************
** Status del Vehículo
** Marca.......................{self.marca}
** Modelo......................{self.modelo}
** Color.......................{self.color}
** Acelerando..................{self.acelerando}
** Frenando....................{self.frenando}
** Detenido....................{self.detenido}
**
**************************************************************************************
''')
vehiculos_bin=open('automoviles.bin','rb')
print('Archivo binario abierto ok')
lista_vehiculos = pickle.load(vehiculos_bin)
print('Data binaria cargada ok')
vehiculos_bin.close()
print('Archivo binario cerrado ok')
print('El contenido del archivo binario es:')
for i in lista_vehiculos:
print('Marca: ',i.marca,'Modelo: ',i.modelo)
i.estado()
Resultado:
Archivo binario abierto ok
Data binaria cargada ok
Archivo binario cerrado ok
El contenido del archivo binario es:
Marca: Ford Modelo: Fiesta
**************************************************************************************
** Status del Vehículo
** Marca.......................Ford
** Modelo......................Fiesta
** Color.......................Blanco
** Acelerando..................False
** Frenando....................False
** Detenido....................True
**
**************************************************************************************
Marca: Chevrolet Modelo: Chevette
**************************************************************************************
** Status del Vehículo
** Marca.......................Chevrolet
** Modelo......................Chevette
** Color.......................Blanco
** Acelerando..................False
** Frenando....................False
** Detenido....................True
**
**************************************************************************************
Marca: Fiat Modelo: Fiorino
**************************************************************************************
** Status del Vehículo
** Marca.......................Fiat
** Modelo......................Fiorino
** Color.......................Blanco
** Acelerando..................False
** Frenando....................False
** Detenido....................True
**
**************************************************************************************
Podemos comprobar que ahora es posible acceder a los objetos exteraidos del archivo binario y Python los puede procesar ya que ahora estan definidas las clases dentro del script que los lee.
Comentarios
Publicar un comentario