Python

Python

Tutorial Python: Módulo pickle

Aprende a usar el módulo pickle en Python para serializar objetos y gestionar la persistencia de datos complejos de forma eficiente y segura.

Aprende Python y certifícate

Serialización de objetos Python

La serialización es el proceso de convertir estructuras de datos complejas, como objetos Python, en un formato que puede ser fácilmente almacenado o transmitido. Cuando necesitamos guardar el estado de nuestros objetos para usarlos más tarde o enviarlos a través de una red, la serialización se convierte en una herramienta fundamental.

Python ofrece varias opciones para serializar datos, siendo el módulo pickle una de las más versátiles para objetos nativos. A diferencia de otros formatos como JSON, pickle está diseñado específicamente para Python y puede manejar casi cualquier objeto Python.

Introducción al módulo pickle

El módulo pickle forma parte de la biblioteca estándar de Python y permite serializar (o "encurtir") objetos Python a un flujo de bytes y deserializarlos (o "desencurtir") de vuelta a objetos Python. Su principal ventaja es la capacidad de preservar la estructura y el estado de objetos complejos.

import pickle

# Un objeto Python complejo
datos = {
    'enteros': [1, 2, 3, 4, 5],
    'flotantes': [1.5, 2.5, 3.5],
    'cadenas': ['uno', 'dos', 'tres'],
    'booleanos': True,
    'ninguno': None,
    'anidado': {'clave': 'valor', 'lista': [1, 2, 3]}
}

# Serialización a bytes
datos_serializados = pickle.dumps(datos)
print(f"Tipo de datos serializados: {type(datos_serializados)}")

Métodos principales de pickle

El módulo pickle proporciona cuatro funciones principales:

  • dumps(obj): Serializa un objeto a una secuencia de bytes.
  • loads(bytes_object): Deserializa bytes a un objeto Python.
  • dump(obj, file): Serializa un objeto y lo escribe a un archivo.
  • load(file): Lee un archivo y deserializa su contenido.

Veamos ejemplos de cada uno:

import pickle

# Objeto de ejemplo
mi_lista = [1, 2, 3, 4, 5]

# Serialización a bytes en memoria
bytes_serializados = pickle.dumps(mi_lista)

# Deserialización desde bytes
lista_recuperada = pickle.loads(bytes_serializados)
print(f"Objeto recuperado: {lista_recuperada}")

# Serialización a un archivo
with open('datos.pickle', 'wb') as archivo:
    pickle.dump(mi_lista, archivo)

# Deserialización desde un archivo
with open('datos.pickle', 'rb') as archivo:
    lista_desde_archivo = pickle.load(archivo)
    print(f"Objeto desde archivo: {lista_desde_archivo}")

Es importante notar que al trabajar con archivos, debemos usar el modo binario ('wb' para escritura y 'rb' para lectura).

Serialización de objetos complejos

Una de las grandes ventajas de pickle es su capacidad para manejar objetos Python complejos, incluyendo instancias de clases personalizadas:

import pickle
from datetime import datetime

class Persona:
    def __init__(self, nombre, edad, fecha_nacimiento):
        self.nombre = nombre
        self.edad = edad
        self.fecha_nacimiento = fecha_nacimiento
        self.momento_creacion = datetime.now()
    
    def __str__(self):
        return f"{self.nombre}, {self.edad} años, nacido el {self.fecha_nacimiento}"

# Crear una instancia
persona = Persona("Ana García", 29, datetime(1994, 5, 12))
print(f"Original: {persona}")

# Serializar y guardar
with open('persona.pickle', 'wb') as archivo:
    pickle.dump(persona, archivo)

# Recuperar
with open('persona.pickle', 'rb') as archivo:
    persona_recuperada = pickle.load(archivo)
    print(f"Recuperada: {persona_recuperada}")

Este ejemplo muestra cómo pickle puede serializar no solo los atributos básicos de un objeto, sino también objetos complejos como instancias de datetime.

Comparación con JSON

Aunque JSON es un formato popular para serialización, tiene limitaciones importantes en comparación con pickle:

import json
import pickle
from datetime import datetime

# Objeto con tipos que JSON no maneja nativamente
datos = {
    'fecha': datetime.now(),
    'conjunto': {1, 2, 3},
    'bytes': b'datos binarios',
    'complejo': 3+4j
}

# Intentar serializar con JSON (fallará)
try:
    json_data = json.dumps(datos)
except TypeError as e:
    print(f"Error al serializar con JSON: {e}")

# Serializar con pickle (funcionará)
pickle_data = pickle.dumps(datos)
datos_recuperados = pickle.loads(pickle_data)
print(f"Fecha recuperada: {datos_recuperados['fecha']}")
print(f"Conjunto recuperado: {datos_recuperados['conjunto']}")

Este ejemplo ilustra que pickle puede manejar tipos de datos que JSON no soporta nativamente, como fechas, conjuntos, bytes y números complejos.

Protocolos de pickle

Pickle ofrece diferentes protocolos que determinan el formato y las características de la serialización:

import pickle

datos = ["una lista", {"un": "diccionario"}, (1, 2, 3)]

# Protocolo 0 (formato ASCII legible por humanos)
bytes_proto0 = pickle.dumps(datos, protocol=0)

# Protocolo más reciente (más eficiente)
bytes_proto_default = pickle.dumps(datos)

# Protocolo específico (Python 3.8+)
bytes_proto5 = pickle.dumps(datos, protocol=5)

print(f"Tamaño con protocolo 0: {len(bytes_proto0)} bytes")
print(f"Tamaño con protocolo por defecto: {len(bytes_proto_default)} bytes")
print(f"Tamaño con protocolo 5: {len(bytes_proto5)} bytes")

En Python 3.13, el protocolo por defecto es el 5, que ofrece mejor rendimiento y características adicionales como la serialización fuera del proceso principal.

Consideraciones de seguridad

Es crucial entender que pickle no es seguro contra datos maliciosos. Nunca debes despicklear datos de fuentes no confiables:

import pickle
import os

# Este es un ejemplo de un objeto pickle malicioso
# ¡NO ejecutes esto en un entorno de producción!
class Malicioso:
    def __reduce__(self):
        # Este código se ejecutaría al despicklear
        return (os.system, ('echo "Este comando podría ser malicioso"',))

# Serializar el objeto malicioso
datos_maliciosos = pickle.dumps(Malicioso())

# Deserializar ejecutaría el comando
# pickle.loads(datos_maliciosos)  # ¡NO ejecutar!

print("ADVERTENCIA: Nunca despicklear datos de fuentes no confiables")

Este ejemplo muestra cómo un objeto pickle malicioso podría ejecutar código arbitrario al ser deserializado. Por esta razón, pickle debe usarse solo con datos de fuentes confiables.

Compatibilidad entre versiones

Un aspecto importante a considerar es que pickle no garantiza la compatibilidad entre diferentes versiones de Python:

import pickle
import sys

datos = ["una lista", {"un": "diccionario"}, (1, 2, 3)]

# Serializar con la versión actual de Python
with open('datos_version.pickle', 'wb') as f:
    pickle.dump(datos, f)
    print(f"Datos serializados con Python {sys.version_info.major}.{sys.version_info.minor}")

# Al cargar estos datos en otra versión de Python podría haber problemas
print("Nota: Los archivos pickle pueden no ser compatibles entre versiones de Python")

Para datos que necesitan ser compartidos entre diferentes versiones de Python o con otros lenguajes, formatos como JSON o XML son más apropiados a pesar de sus limitaciones.

Casos de uso prácticos

Pickle es especialmente útil en escenarios como:

import pickle
import time

# 1. Caché de resultados costosos
def calculo_costoso(n):
    print(f"Realizando cálculo costoso para {n}...")
    time.sleep(2)  # Simulando un cálculo que toma tiempo
    return n * n * n

def obtener_resultado(n, usar_cache=True):
    archivo_cache = f'cache_{n}.pickle'
    
    if usar_cache:
        try:
            with open(archivo_cache, 'rb') as f:
                return pickle.load(f)
        except FileNotFoundError:
            pass
    
    resultado = calculo_costoso(n)
    
    # Guardar en caché para uso futuro
    with open(archivo_cache, 'wb') as f:
        pickle.dump(resultado, f)
    
    return resultado

# Primera ejecución (sin caché)
t_inicio = time.time()
resultado1 = obtener_resultado(5)
print(f"Tiempo: {time.time() - t_inicio:.2f}s, Resultado: {resultado1}")

# Segunda ejecución (con caché)
t_inicio = time.time()
resultado2 = obtener_resultado(5)
print(f"Tiempo: {time.time() - t_inicio:.2f}s, Resultado: {resultado2}")

Este ejemplo muestra cómo pickle puede usarse para implementar un sistema de caché simple, almacenando resultados de cálculos costosos para su reutilización.

Serialización de funciones y clases

Pickle también puede serializar funciones y clases, aunque con algunas limitaciones:

import pickle

# Función que queremos serializar
def saludar(nombre):
    return f"¡Hola, {nombre}!"

# Serializar la función
with open('funcion.pickle', 'wb') as f:
    pickle.dump(saludar, f)

# Cargar la función
with open('funcion.pickle', 'rb') as f:
    funcion_cargada = pickle.load(f)

# Usar la función cargada
print(funcion_cargada("María"))

Sin embargo, es importante tener en cuenta que pickle solo guarda referencias a funciones y clases, no su definición completa. Esto significa que al cargar el objeto, Python debe poder encontrar la definición de la función o clase en el mismo módulo y con el mismo nombre.

Persistencia de datos

La persistencia de datos se refiere a la capacidad de almacenar información de manera que sobreviva más allá de la ejecución del programa que la creó. En Python, el módulo pickle proporciona un mecanismo eficiente para implementar persistencia de datos complejos, permitiendo guardar y recuperar el estado de objetos entre diferentes sesiones de ejecución.

Estrategias de persistencia con pickle

Cuando trabajamos con aplicaciones que necesitan mantener su estado, pickle ofrece varias estrategias para implementar persistencia:

import pickle
import os

class GestorPersistencia:
    def __init__(self, archivo):
        self.ruta_archivo = archivo
        
    def guardar_datos(self, datos):
        with open(self.ruta_archivo, 'wb') as f:
            pickle.dump(datos, f)
            
    def cargar_datos(self):
        if not os.path.exists(self.ruta_archivo):
            return None
        
        with open(self.ruta_archivo, 'rb') as f:
            return pickle.load(f)

Este patrón básico puede adaptarse a diferentes necesidades de persistencia, desde configuraciones de aplicaciones hasta el estado completo de un programa.

Persistencia automática

Podemos implementar un sistema que guarde automáticamente el estado de nuestra aplicación:

import pickle
import atexit
import os

class AplicacionPersistente:
    def __init__(self, archivo_estado='estado_app.pickle'):
        self.archivo_estado = archivo_estado
        self.datos = self._cargar_estado()
        # Registrar función para guardar al salir
        atexit.register(self._guardar_estado)
    
    def _cargar_estado(self):
        if os.path.exists(self.archivo_estado):
            try:
                with open(self.archivo_estado, 'rb') as f:
                    return pickle.load(f)
            except (pickle.PickleError, EOFError):
                print("Error al cargar estado, iniciando con datos nuevos")
        return {'contador': 0, 'historial': []}
    
    def _guardar_estado(self):
        with open(self.archivo_estado, 'wb') as f:
            pickle.dump(self.datos, f)
        print(f"Estado guardado en {self.archivo_estado}")
    
    def incrementar_contador(self):
        self.datos['contador'] += 1
        self.datos['historial'].append(f"Incremento a {self.datos['contador']}")
        
    def mostrar_estado(self):
        print(f"Contador: {self.datos['contador']}")
        print(f"Historial: {self.datos['historial'][-3:]}")  # Últimos 3 eventos

# Uso de la aplicación
app = AplicacionPersistente()
app.mostrar_estado()
app.incrementar_contador()
app.incrementar_contador()
app.mostrar_estado()
# Al salir, el estado se guardará automáticamente

Este ejemplo implementa una aplicación que carga su estado anterior al iniciar y lo guarda automáticamente al finalizar, proporcionando continuidad entre ejecuciones.

Persistencia incremental

Para aplicaciones que manejan grandes volúmenes de datos, puede ser más eficiente implementar una estrategia de persistencia incremental:

import pickle
import os
import time

class RegistroActividad:
    def __init__(self, directorio='registros'):
        self.directorio = directorio
        os.makedirs(directorio, exist_ok=True)
        self.registros = []
        self.ultimo_guardado = time.time()
        self.intervalo_guardado = 10  # segundos
        
    def agregar_evento(self, evento):
        timestamp = time.time()
        self.registros.append((timestamp, evento))
        
        # Guardar si han pasado más de 10 segundos desde el último guardado
        if timestamp - self.ultimo_guardado > self.intervalo_guardado:
            self.guardar_registros()
    
    def guardar_registros(self):
        if not self.registros:
            return
            
        nombre_archivo = f"{self.directorio}/registro_{int(time.time())}.pickle"
        with open(nombre_archivo, 'wb') as f:
            pickle.dump(self.registros, f)
        
        print(f"Guardados {len(self.registros)} eventos en {nombre_archivo}")
        self.registros = []  # Limpiar registros guardados
        self.ultimo_guardado = time.time()
    
    def cargar_todos_registros(self):
        todos_registros = []
        archivos = sorted([f for f in os.listdir(self.directorio) if f.endswith('.pickle')])
        
        for archivo in archivos:
            ruta_completa = os.path.join(self.directorio, archivo)
            with open(ruta_completa, 'rb') as f:
                registros = pickle.load(f)
                todos_registros.extend(registros)
        
        return sorted(todos_registros, key=lambda x: x[0])  # Ordenar por timestamp

# Ejemplo de uso
registro = RegistroActividad()
for i in range(5):
    registro.agregar_evento(f"Acción {i}")
    time.sleep(2)  # Simular tiempo entre eventos

registro.guardar_registros()  # Guardar registros pendientes

Este enfoque es útil para sistemas de registro o aplicaciones que necesitan guardar datos continuamente sin perderlos en caso de fallos.

Persistencia de configuraciones

Pickle es ideal para almacenar configuraciones complejas de aplicaciones:

import pickle
import os

class Configuracion:
    def __init__(self):
        # Valores predeterminados
        self.tema = "claro"
        self.fuente = "Arial"
        self.tamano_fuente = 12
        self.mostrar_barra_herramientas = True
        self.plugins_activos = ["editor", "explorador", "terminal"]
        self.atajos_teclado = {
            "guardar": "Ctrl+S",
            "abrir": "Ctrl+O",
            "nuevo": "Ctrl+N"
        }
    
    @classmethod
    def cargar(cls, ruta="config.pickle"):
        if os.path.exists(ruta):
            try:
                with open(ruta, 'rb') as f:
                    return pickle.load(f)
            except Exception as e:
                print(f"Error al cargar configuración: {e}")
        
        # Si no existe o hay error, crear configuración por defecto
        return cls()
    
    def guardar(self, ruta="config.pickle"):
        with open(ruta, 'wb') as f:
            pickle.dump(self, f)
        print(f"Configuración guardada en {ruta}")

# Uso
config = Configuracion.cargar()
print(f"Tema actual: {config.tema}")

# Modificar configuración
config.tema = "oscuro"
config.tamano_fuente = 14
config.plugins_activos.append("depurador")

# Guardar cambios
config.guardar()

Este patrón permite a las aplicaciones recordar las preferencias del usuario entre sesiones.

Persistencia de estado en aplicaciones interactivas

Para aplicaciones interactivas como juegos o herramientas de edición, pickle facilita la implementación de funciones de guardado:

import pickle
import os
from datetime import datetime

class EditorDocumento:
    def __init__(self):
        self.contenido = ""
        self.historial_cambios = []
        self.nombre_archivo = "sin_titulo"
        self.ultima_modificacion = None
    
    def escribir(self, texto):
        self.contenido += texto
        self.registrar_cambio(f"Añadido: {texto[:20]}...")
    
    def borrar(self, cantidad):
        if cantidad <= len(self.contenido):
            texto_borrado = self.contenido[-cantidad:]
            self.contenido = self.contenido[:-cantidad]
            self.registrar_cambio(f"Borrado: {texto_borrado}")
    
    def registrar_cambio(self, descripcion):
        ahora = datetime.now()
        self.historial_cambios.append((ahora, descripcion))
        self.ultima_modificacion = ahora
    
    def guardar(self, nombre=None):
        if nombre:
            self.nombre_archivo = nombre
        
        nombre_completo = f"{self.nombre_archivo}.pickle"
        with open(nombre_completo, 'wb') as f:
            pickle.dump(self, f)
        print(f"Documento guardado como {nombre_completo}")
    
    @classmethod
    def abrir(cls, nombre):
        nombre_completo = f"{nombre}.pickle"
        if not os.path.exists(nombre_completo):
            raise FileNotFoundError(f"No se encontró el archivo {nombre_completo}")
        
        with open(nombre_completo, 'rb') as f:
            return pickle.load(f)
    
    def mostrar_info(self):
        print(f"Documento: {self.nombre_archivo}")
        print(f"Longitud: {len(self.contenido)} caracteres")
        print(f"Última modificación: {self.ultima_modificacion}")
        print(f"Cambios registrados: {len(self.historial_cambios)}")

# Ejemplo de uso
editor = EditorDocumento()
editor.escribir("Este es un documento de prueba.\n")
editor.escribir("Tiene múltiples líneas de texto.\n")
editor.borrar(5)
editor.escribir("contenido.")
editor.guardar("documento_prueba")

# En otra sesión podríamos recuperarlo
documento_recuperado = EditorDocumento.abrir("documento_prueba")
documento_recuperado.mostrar_info()
print("\nContenido:")
print(documento_recuperado.contenido)

Este ejemplo muestra cómo implementar funcionalidad de guardado y carga en una aplicación de edición de texto.

Persistencia con control de versiones

Para aplicaciones que necesitan mantener compatibilidad entre diferentes versiones, podemos implementar un sistema de control de versiones:

import pickle
import os

class DatosAplicacionV1:
    def __init__(self):
        self.version = 1
        self.contador = 0
        self.notas = []

class DatosAplicacionV2:
    def __init__(self):
        self.version = 2
        self.contador = 0
        self.notas = []
        self.configuracion = {"tema": "claro"}  # Campo nuevo en V2

def cargar_datos(ruta="datos_app.pickle"):
    if not os.path.exists(ruta):
        return DatosAplicacionV2()  # Versión actual
    
    with open(ruta, 'rb') as f:
        datos = pickle.load(f)
    
    # Migrar datos si es necesario
    if hasattr(datos, 'version') and datos.version < 2:
        print("Actualizando datos de V1 a V2...")
        datos_v2 = DatosAplicacionV2()
        datos_v2.contador = datos.contador
        datos_v2.notas = datos.notas
        return datos_v2
    
    return datos

def guardar_datos(datos, ruta="datos_app.pickle"):
    with open(ruta, 'wb') as f:
        pickle.dump(datos, f)
    print(f"Datos guardados en {ruta}")

# Simular datos de versión anterior
datos_v1 = DatosAplicacionV1()
datos_v1.contador = 42
datos_v1.notas = ["Nota importante", "Recordatorio"]
guardar_datos(datos_v1)

# Cargar y actualizar automáticamente
datos_actuales = cargar_datos()
print(f"Versión de datos: {datos_actuales.version}")
print(f"Contador: {datos_actuales.contador}")
print(f"Notas: {datos_actuales.notas}")
print(f"Configuración: {datos_actuales.configuracion}")

Este patrón permite que la aplicación evolucione mientras mantiene la capacidad de leer datos guardados con versiones anteriores.

Persistencia con respaldo

Para datos críticos, es recomendable implementar un sistema de respaldo antes de sobrescribir archivos existentes:

import pickle
import os
import shutil
from datetime import datetime

def guardar_con_respaldo(datos, ruta, max_respaldos=5):
    # Crear directorio de respaldos si no existe
    dir_respaldos = os.path.join(os.path.dirname(ruta), "respaldos")
    os.makedirs(dir_respaldos, exist_ok=True)
    
    # Si existe el archivo, crear respaldo
    if os.path.exists(ruta):
        nombre_base = os.path.basename(ruta)
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        ruta_respaldo = os.path.join(dir_respaldos, f"{nombre_base}_{timestamp}")
        shutil.copy2(ruta, ruta_respaldo)
        print(f"Respaldo creado: {ruta_respaldo}")
        
        # Limitar número de respaldos
        respaldos = sorted([os.path.join(dir_respaldos, f) for f in os.listdir(dir_respaldos)])
        while len(respaldos) > max_respaldos:
            os.remove(respaldos[0])
            respaldos.pop(0)
    
    # Guardar datos actuales
    with open(ruta, 'wb') as f:
        pickle.dump(datos, f)
    print(f"Datos guardados en {ruta}")

# Ejemplo de uso
datos = {"usuario": "admin", "preferencias": {"tema": "oscuro"}, "historial": [1, 2, 3]}
guardar_con_respaldo(datos, "datos_importantes.pickle")

Esta implementación crea automáticamente copias de seguridad antes de sobrescribir datos, permitiendo recuperar versiones anteriores en caso de corrupción o pérdida de datos.

Consideraciones para la persistencia a largo plazo

Cuando implementamos persistencia para datos que deben mantenerse durante largos períodos, debemos considerar:

import pickle
import json
import os

class RegistroPersistente:
    def __init__(self, nombre):
        self.nombre = nombre
        self.datos = {}
        self.formato_preferido = "pickle"  # o "json"
    
    def guardar(self):
        # Guardar en ambos formatos para mayor compatibilidad
        self._guardar_pickle()
        self._guardar_json()
    
    def _guardar_pickle(self):
        with open(f"{self.nombre}.pickle", 'wb') as f:
            pickle.dump(self.datos, f, protocol=4)  # Protocolo compatible
    
    def _guardar_json(self):
        # Convertir tipos no serializables en JSON
        datos_json = {}
        for clave, valor in self.datos.items():
            # Simplificar para JSON si es necesario
            if isinstance(valor, set):
                datos_json[clave] = list(valor)
            elif isinstance(valor, bytes):
                datos_json[clave] = valor.decode('utf-8', errors='replace')
            else:
                try:
                    # Verificar si es serializable en JSON
                    json.dumps(valor)
                    datos_json[clave] = valor
                except (TypeError, OverflowError):
                    # Si no es serializable, convertir a string
                    datos_json[clave] = str(valor)
        
        with open(f"{self.nombre}.json", 'w', encoding='utf-8') as f:
            json.dump(datos_json, f, indent=2)
    
    def cargar(self):
        # Intentar cargar pickle primero (más completo)
        pickle_path = f"{self.nombre}.pickle"
        json_path = f"{self.nombre}.json"
        
        if os.path.exists(pickle_path) and self.formato_preferido == "pickle":
            try:
                with open(pickle_path, 'rb') as f:
                    self.datos = pickle.load(f)
                return True
            except Exception as e:
                print(f"Error al cargar pickle: {e}")
        
        # Intentar JSON como respaldo
        if os.path.exists(json_path):
            try:
                with open(json_path, 'r', encoding='utf-8') as f:
                    self.datos = json.load(f)
                return True
            except Exception as e:
                print(f"Error al cargar JSON: {e}")
        
        return False

# Ejemplo
registro = RegistroPersistente("datos_app")
registro.datos = {
    "configuracion": {"tema": "oscuro", "idioma": "es"},
    "usuarios": ["admin", "invitado"],
    "estadisticas": {1: 100, 2: 200},
    "conjunto_valores": {1, 2, 3, 4}  # No serializable en JSON directamente
}
registro.guardar()

Esta implementación híbrida proporciona mayor robustez para la persistencia a largo plazo, guardando los datos en múltiples formatos para asegurar la recuperabilidad futura.

Optimización de la persistencia

Para aplicaciones que manejan grandes volúmenes de datos, podemos optimizar el proceso de persistencia:

import pickle
import gzip
import time
import os

def guardar_comprimido(datos, ruta):
    """Guarda datos pickle con compresión gzip"""
    inicio = time.time()
    with gzip.open(ruta, 'wb', compresslevel=9) as f:
        pickle.dump(datos, f)
    
    tamaño = os.path.getsize(ruta)
    tiempo = time.time() - inicio
    print(f"Datos guardados en {ruta}")
    print(f"Tamaño: {tamaño/1024:.2f} KB, Tiempo: {tiempo:.2f}s")

def cargar_comprimido(ruta):
    """Carga datos pickle comprimidos con gzip"""
    inicio = time.time()
    with gzip.open(ruta, 'rb') as f:
        datos = pickle.load(f)
    
    tiempo = time.time() - inicio
    print(f"Datos cargados desde {ruta} en {tiempo:.2f}s")
    return datos

# Generar datos de prueba (10,000 elementos)
datos_grandes = {i: f"Valor {i}" * 100 for i in range(10000)}

# Comparar tamaños y tiempos
print("Guardando sin compresión...")
inicio = time.time()
with open("datos_grandes.pickle", 'wb') as f:
    pickle.dump(datos_grandes, f)
tamaño_normal = os.path.getsize("datos_grandes.pickle")
tiempo_normal = time.time() - inicio
print(f"Tamaño: {tamaño_normal/1024:.2f} KB, Tiempo: {tiempo_normal:.2f}s")

print("\nGuardando con compresión...")
guardar_comprimido(datos_grandes, "datos_grandes.pickle.gz")

# Cargar datos comprimidos
datos_recuperados = cargar_comprimido("datos_grandes.pickle.gz")
print(f"Elementos recuperados: {len(datos_recuperados)}")

La compresión puede reducir significativamente el tamaño de los archivos pickle, especialmente para datos con patrones repetitivos, a costa de un ligero aumento en el tiempo de procesamiento.

CONSTRUYE TU CARRERA EN IA Y PROGRAMACIÓN SOFTWARE

Accede a +1000 lecciones y cursos con certificado. Mejora tu portfolio con certificados de superación para tu CV.

30 % DE DESCUENTO

Plan mensual

19.00 /mes

13.30 € /mes

Precio normal mensual: 19 €
63 % DE DESCUENTO

Plan anual

10.00 /mes

7.00 € /mes

Ahorras 144 € al año
Precio normal anual: 120 €
Aprende Python online

Ejercicios de esta lección Módulo pickle

Evalúa tus conocimientos de esta lección Módulo pickle con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Módulo math

Python
Puzzle

Reto herencia

Python
Código

Excepciones

Python
Test

Introducción a Python

Python
Test

Reto variables

Python
Código

Funciones Python

Python
Puzzle

Reto funciones

Python
Código

Módulo datetime

Python
Test

Reto acumulación

Python
Código

Reto estructuras condicionales

Python
Código

Polimorfismo

Python
Test

Módulo os

Python
Test

Reto métodos dunder

Python
Código

Diccionarios

Python
Puzzle

Reto clases y objetos

Python
Código

Reto operadores

Python
Código

Operadores

Python
Test

Estructuras de control

Python
Puzzle

Funciones lambda

Python
Test

Reto diccionarios

Python
Código

Reto función lambda

Python
Código

Encapsulación

Python
Puzzle

Reto coleciones

Python
Proyecto

Reto funciones auxiliares

Python
Código

Crear módulos y paquetes

Python
Puzzle

Módulo datetime

Python
Puzzle

Excepciones

Python
Puzzle

Operadores

Python
Puzzle

Diccionarios

Python
Test

Reto map, filter

Python
Código

Reto tuplas

Python
Código

Proyecto gestor de tareas CRUD

Python
Proyecto

Tuplas

Python
Puzzle

Variables

Python
Puzzle

Tipos de datos

Python
Puzzle

Conjuntos

Python
Test

Reto mixins

Python
Código

Módulo csv

Python
Test

Módulo json

Python
Test

Herencia

Python
Test

Análisis de datos de ventas con Pandas

Python
Proyecto

Reto fechas y tiempo

Python
Proyecto

Reto estructuras de iteración

Python
Código

Funciones

Python
Test

Reto comprehensions

Python
Código

Variables

Python
Test

Reto serialización

Python
Proyecto

Módulo csv

Python
Puzzle

Reto polimorfismo

Python
Código

Polimorfismo

Python
Puzzle

Clases y objetos

Python
Código

Reto encapsulación

Python
Código

Estructuras de control

Python
Test

Importar módulos y paquetes

Python
Test

Módulo math

Python
Test

Funciones lambda

Python
Puzzle

Reto excepciones

Python
Código

Listas

Python
Puzzle

Reto archivos

Python
Proyecto

Encapsulación

Python
Test

Reto conjuntos

Python
Código

Clases y objetos

Python
Test

Instalación de Python y creación de proyecto

Python
Test

Reto listas

Python
Código

Tipos de datos

Python
Test

Crear módulos y paquetes

Python
Test

Tuplas

Python
Test

Herencia

Python
Puzzle

Reto acceso a sistema

Python
Proyecto

Proyecto sintaxis calculadora

Python
Proyecto

Importar módulos y paquetes

Python
Puzzle

Clases y objetos

Python
Puzzle

Módulo os

Python
Puzzle

Listas

Python
Test

Conjuntos

Python
Puzzle

Reto tipos de datos

Python
Código

Reto matemáticas

Python
Proyecto

Módulo json

Python
Puzzle

Todas las lecciones de Python

Accede a todas las lecciones de Python y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Python

Python

Introducción

Instalación Y Creación De Proyecto

Python

Introducción

Tema 2: Tipos De Datos, Variables Y Operadores

Python

Introducción

Instalación De Python

Python

Introducción

Tipos De Datos

Python

Sintaxis

Variables

Python

Sintaxis

Operadores

Python

Sintaxis

Estructuras De Control

Python

Sintaxis

Funciones

Python

Sintaxis

Estructuras Control Iterativo

Python

Sintaxis

Estructuras Control Condicional

Python

Sintaxis

Testing Con Pytest

Python

Sintaxis

Listas

Python

Estructuras De Datos

Tuplas

Python

Estructuras De Datos

Diccionarios

Python

Estructuras De Datos

Conjuntos

Python

Estructuras De Datos

Comprehensions

Python

Estructuras De Datos

Clases Y Objetos

Python

Programación Orientada A Objetos

Excepciones

Python

Programación Orientada A Objetos

Encapsulación

Python

Programación Orientada A Objetos

Herencia

Python

Programación Orientada A Objetos

Polimorfismo

Python

Programación Orientada A Objetos

Mixins Y Herencia Múltiple

Python

Programación Orientada A Objetos

Métodos Especiales (Dunder Methods)

Python

Programación Orientada A Objetos

Composición De Clases

Python

Programación Orientada A Objetos

Funciones Lambda

Python

Programación Funcional

Aplicación Parcial

Python

Programación Funcional

Entrada Y Salida, Manejo De Archivos

Python

Programación Funcional

Decoradores

Python

Programación Funcional

Generadores

Python

Programación Funcional

Paradigma Funcional

Python

Programación Funcional

Composición De Funciones

Python

Programación Funcional

Funciones Orden Superior Map Y Filter

Python

Programación Funcional

Funciones Auxiliares

Python

Programación Funcional

Reducción Y Acumulación

Python

Programación Funcional

Archivos Comprimidos

Python

Entrada Y Salida Io

Entrada Y Salida Avanzada

Python

Entrada Y Salida Io

Archivos Temporales

Python

Entrada Y Salida Io

Contexto With

Python

Entrada Y Salida Io

Módulo Csv

Python

Biblioteca Estándar

Módulo Json

Python

Biblioteca Estándar

Módulo Datetime

Python

Biblioteca Estándar

Módulo Math

Python

Biblioteca Estándar

Módulo Os

Python

Biblioteca Estándar

Módulo Re

Python

Biblioteca Estándar

Módulo Random

Python

Biblioteca Estándar

Módulo Time

Python

Biblioteca Estándar

Módulo Collections

Python

Biblioteca Estándar

Módulo Sys

Python

Biblioteca Estándar

Módulo Statistics

Python

Biblioteca Estándar

Módulo Pickle

Python

Biblioteca Estándar

Módulo Pathlib

Python

Biblioteca Estándar

Importar Módulos Y Paquetes

Python

Paquetes Y Módulos

Crear Módulos Y Paquetes

Python

Paquetes Y Módulos

Entornos Virtuales (Virtualenv, Venv)

Python

Entorno Y Dependencias

Gestión De Dependencias (Pip, Requirements.txt)

Python

Entorno Y Dependencias

Python-dotenv Y Variables De Entorno

Python

Entorno Y Dependencias

Acceso A Datos Con Mysql, Pymongo Y Pandas

Python

Acceso A Bases De Datos

Acceso A Mongodb Con Pymongo

Python

Acceso A Bases De Datos

Acceso A Mysql Con Mysql Connector

Python

Acceso A Bases De Datos

Novedades Python 3.13

Python

Características Modernas

Operador Walrus

Python

Características Modernas

Pattern Matching

Python

Características Modernas

Instalación Beautiful Soup

Python

Web Scraping

Sintaxis General De Beautiful Soup

Python

Web Scraping

Tipos De Selectores

Python

Web Scraping

Web Scraping De Html

Python

Web Scraping

Web Scraping Para Ciencia De Datos

Python

Web Scraping

Autenticación Y Acceso A Recursos Protegidos

Python

Web Scraping

Combinación De Selenium Con Beautiful Soup

Python

Web Scraping

Accede GRATIS a Python y certifícate

En esta lección

Objetivos de aprendizaje de esta lección

  • Comprender el concepto de serialización y su importancia en Python.
  • Aprender a usar las funciones principales del módulo pickle para serializar y deserializar objetos.
  • Conocer las ventajas y limitaciones de pickle frente a otros formatos como JSON.
  • Implementar estrategias de persistencia de datos usando pickle en aplicaciones reales.
  • Identificar consideraciones de seguridad y compatibilidad al usar pickle.