Última actualización: 15 de diciembre de 2023

2.1. Serialización de objetos

Nota

Propósito: es una libraría para implementa protocolos binarios para serializar y deserializar una estructura de objetos Python, es decir, convertirlos en un flujo de bytes que se puede almacenar o transmitir por una red.

La serialización es el proceso de convertir un objeto en una secuencia de bytes para almacenarlo o transmitirlo a la memoria, a una base de datos o a un archivo. Su propósito principal es guardar el estado de un objeto para poder volver a crearlo cuando sea necesario. El proceso inverso se denomina deserialización.

Por ejemplo, guardar una lista de Python en un archivo de texto o base de datos, y luego cargarlo cuando sea necesario, para ser tratado con su tipo de datos.

Formatos comunes entre los distintos lenguajes de programación incluyen XML y JSON.

Python ofrece tres módulos diferentes en la biblioteca estándar que le permiten serializar y deserializar objetos:

2.1.1. pickle

Por hacer

TODO Terminar de escribir esta sección.

2.1.1.1. Serializar

Por hacer

TODO terminar de escribir esta sección.

2.1.1.2. Deserializar

Por hacer

TODO terminar de escribir esta sección.

2.1.1.3. Práctica - Caso real

A continuación se presenta una práctica más real de implementar el uso de proyectos con pickle para operaciones CRUD en un archivo de registros serializados:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
"""Modulo de Main"""

import os
from pathlib import Path
import pickle

class Producto:
    """Clase Producto"""

    def __init__(self, id, descripcion):
        """Método constructor de clase de Producto

        Args:
            id (int): ID del producto
            descripcion (str): Descripción del producto
        """
        self.id = id
        self.descripcion = descripcion

    def __str__(self):
        """Método de representación de informal del objeto,
        usado para crear la salida que se le mostrará al usuario"""
        return "Id: {0}\nDescripción: {1}".format(self.id, self.descripcion)

    def __repr__(self):
        """Método de representación de formal del objeto,
        usado para depuración y desarrollo"""
        return f'{self.__class__.__name__}:({repr(self.id)}, {repr(self.descripcion)})'


class Inventario:
    """Clase Inventario"""

    def __init__(self):
        """Método constructor de clase de Inventario"""
        self._DB_DIR = os.path.dirname(os.path.abspath(__file__)) + os.sep + 'filestorage/'
        self.productos = []
        self.archivo = self._DB_DIR + "inventario.pkl"
        self.leer_datos()

    def __str__(self):
        """Método de representación de informal del objeto,
        usado para crear la salida que se le mostrará al usuario"""
        return "Ruta BD: {0}".format(self.archivo)

    def __repr__(self):
        """Método de representación de formal del objeto,
        usado para depuración y desarrollo"""
        return f'{self.__class__.__name__}:({repr(self.archivo)})'


    def leer_datos(self):
        """Leer el archivo de almacenamiento"""
        try:
            Path(self._DB_DIR).mkdir(parents=True, exist_ok=True)
            with open(self.archivo, 'rb') as bd:
                self.productos = pickle.load(bd)
        except IOError:
            print("El archivo no existe en la ubicación")


    def guardar_datos(self):
        """Guarda los datos"""
        try:
            if os.path.isfile(self.archivo):
                os.remove(self.archivo)
            with open(self.archivo, 'wb') as bd:
                pickle.dump(self.productos, bd)
        except IOError:
            print("El archivo no existe en la ubicación")


    def existe(self, codigo):
        """Valida si existe el producto

        Args:
            codigo (int): ID del producto
        """
        if self.productos:
            for producto in self.productos:
                if producto.id == codigo:
                    return True
        return False


    def buscar(self, codigo):
        """Buscar el producto en el Inventario

        Args:
            codigo (int): ID del producto
        """
        for posicion, producto in enumerate(self.productos):
            if producto.id == codigo:
                return posicion, producto
        return 0, None


    def agregar_registro(self, codigo):
        """Agregar el producto

        Args:
            codigo (int): ID del producto
        """
        descripcion = input("Descripción: ")
        producto = Producto(codigo, descripcion)
        self.productos.append(producto)
        self.guardar_datos()


    def mostrar_registro(self, codigo):
        """Mostrar el producto

        Args:
            codigo (int): ID del producto
        """
        if self.existe(codigo):
            posicion, producto = self.buscar(codigo)
            print(producto)
        else:
            print("¡El producto no existe!")
        input("Presione ENTER para continuar")


    def actualizar_registro(self, codigo):
        """Actualizar el producto

        Args:
            codigo (int): ID del producto
        """
        if self.existe(codigo):
            posicion, producto = self.buscar(codigo)
            print(producto)
            print("Escribe nuevos datos: ")
            descripcion = input("Descripción: ")
            self.productos[posicion].descripcion = descripcion
            self.guardar_datos()
            print("¡Actualizado exitosamente!")
        else:
            print("¡El producto no existe!")
        input("Presione ENTER para continuar")


    def eliminar_registro(self, codigo):
        """Eliminar el producto

        Args:
            codigo (int): ID del producto
        """
        if self.existe(codigo):
            posicion, producto = self.buscar(codigo)
            print(producto)
            confirmar = input("Estas seguro? (S/N): ").upper()
            if confirmar in ("s", "S", "si", "Si", "SI"):
                del self.productos[posicion]
                self.guardar_datos()
                print("¡Eliminado exitosamente!")
        else:
            print("¡El producto no existe!")
        input("Presione ENTER para continuar")


    def menu_principal(self):
        """Menu principal del programa"""
        try:
            while True:
                print("\n==============")
                print("MENÚ PRINCIPAL")
                print("==============\n")
                opciones_menu = "1) Crear\n"
                opciones_menu += "2) Consultar\n"
                opciones_menu += "3) Actualizar\n"
                opciones_menu += "4) Eliminar\n"
                opciones_menu += "5) Salir\n"
                opciones_menu += "\nElija uno: "

                opcion = int(input(opciones_menu))

                inventario = Inventario()

                if opcion == 1:
                    codigo = int(input("Id de Producto: "))
                    if not inventario.existe(codigo):
                        inventario.agregar_registro(codigo)
                        print("¡Registro exitoso!")
                    else:
                        print("¡Producto ya existe!")
                    input("Presione ENTER para continuar")
                elif opcion == 2:
                    codigo = int(input("Id de Producto: "))
                    inventario.mostrar_registro(codigo)
                elif opcion == 3:
                    codigo = int(input("Id de Producto: "))
                    inventario.actualizar_registro(codigo)
                elif opcion == 4:
                    codigo = int(input("Id de Producto: "))
                    inventario.eliminar_registro(codigo)
                elif opcion == 5:
                    break
        except KeyboardInterrupt:
            import sys
            print()
            sys.exit()


if __name__ == '__main__':
    app = Inventario()
    app.menu_principal()

Importante

Usted puede descargar el código usado en esta sección haciendo clic en el siguiente enlace: main.py.

Truco

Para ejecutar el código main.py, abra una consola de comando, acceda al directorio donde se encuentra ambos programas:

leccion2/
└── pickle/
    └── main.py

Si tiene la estructura de archivo previa, entonces ejecute el siguiente comando:

$ python main.py

Asi de esta forma puede ingresar, consultar, actualizar y eliminar registro en un archivo serializado de objetos python pickle.



Ver también

Consulte la sección de lecturas suplementarias