Python Pickle: qué es y por qué utlizar esta serialización

11min

En Python tenemos un módulo específico para serializar y deserializar objetos, que nos aporta funcionalidades útiles más allá de otros formatos como el simple JSON. Se llama Python Pickle.

Índice

¿Qué es Pickle en Python?

Pickle es un módulo disponible en la biblioteca estándar de Python que permite transformar objetos en una secuencias de bytes, que podemos luego reconstruir en objetos en memoria.

El proceso de crear archivos binarios a partir de objetos y estructuras de datos se llama «serialización» y el paso contrario se denomina «deserialización». Sirven para guardar estados en sistemas de almacenamiento o intercambiar datos y se utilizan frecuentemente para mantener persistencia entre ejecuciones sin tener que escribir código adicional para convertir estructuras a texto o JSON.

¿Por qué usar Pickle en Python?

Como sistema de serialización Pickle nos permite algunas funciones importantes que vamos a describir.

Almacenamiento de estados

Pickle permite guardar el estado de un programa, de modo que podamos retomar más adelante la ejecución de esa aplicación manteniendo todos los datos que tenía en el instante en el que se detuvo.

Intercambio de datos entre procesos

También nos puede servir para intercambiar datos entre procesos dentro de un ordenador, por ejemplo cuando varios procesos se ejecutan de manera concurrente en el sistema.

Persistencia de datos entre sesiones

La serialización también se usa para almacenar datos en disco, de modo que consigamos persistencia entre sesiones dentro de un mismo software. Esto permite que podamos guardar los objetos serializados en un sistema de almacenamiento, como el disco duro del ordenador, de modo que podamos luego recuperarlos incluso, días más tarde y tras reiniciar el equipo.

Simplifica el almacenamiento de estructuras de datos personalizadas

La serialización es un proceso común que viene incorporado en la biblioteca estándar del lenguaje Python, así como en otros lenguajes de programación tienen sus propios mecanismos. Esto permite que las aplicaciones puedan almacenar el estado de una manera sencilla, sin tener que complicar la vida de los desarrolladores creando mecanismos personalizados de guardado.

Facilita la transferencia de datos entre scripts Python

Una vez serializado un objeto es posible hacer cualquier tipo de operación con él.  Esto lo podemos utilizar potencialmente para muchos tipos de funcionalidades, como por ejemplo transferir datos entre programas desarrollados en Python.

Es parte de la biblioteca estándar de Python

Gracias a Pickle no necesitamos añadir dependencias externas a las aplicaciones, ya que simplemente tenemos que usar la biblioteca estándar del lenguaje, disponible en cualquier lugar donde se esté usando Python.

¿Cómo funciona la serialización con Pickle?

Ya de manera práctica, vamos a ver qué necesitas hacer para conseguir serializar objetos usando Pickle en Python.

Métodos dump() y load()

Primero vamos a conocer los métodos dump() y load() que son los más esenciales para usar Pickle.

  • pickle.dump(obj, file) sirve para serializar un objeto. Este método se encarga de guardar el objeto serializado directamente en un archivo.
  • pickle.load(file) hace el paso contrario, toma el contenido de un archivo y lo deserializa, devolviendo un objeto restaurado.

Formatos binarios y de texto

A diferencia de otros formatos, Pickle almacena los datos en un archivo binario, lo que permite un almacenamiento con características más poderosas. Por ejemplo, un archivo binario puede almacenar más información de los objetos, como métodos que no suelen tener una representación fácil en el texto. También es más rápido que un almacenamiento en texto y ocupa menos espacio.

De todos modos, si fuera necesario, Python también podría serializar a un archivo de texto, algo que no es muy habitual porque no ofrece una ventaja destacable, ya que el formato de serialización que se produce es propio de Python, por lo que no podrías usarlo como medio de intercambio en aplicaciones en otros lenguajes.

Tipos de objetos compatibles con Pickle

Pickle es muy versátil en lo que respecta a los tipos de objetos que soporta, aunque no puede serializar todo tipo de objetos. Soporta listas, diccionarios, tuplas, conjuntos, números, cadenas, funciones, incluso objetos de clases personalizadas realizadas por un desarrollo común.

De todos modos, es importante saber que no todos los objetos son serializables mediante Pickle. Por ejemplo no puede serializar descriptores de archivo abiertos o conexiones de red.

Para que sea serializable tiene que ser un objeto de una clase definida en un módulo superior. No podrías por ejemplo si está la clase dentro de una función lambda, ya que Python necesita conocer la clase cuando realiza la deserialización.

Ejemplo práctico de uso de Pickle en Python

Vamos a ver ahora ejemplos concretos de código para ver cómo funciona la serialización en Python con Pickle.

Serializar una lista o diccionario

Este código nos permite ver cómo se serializa un diccionario en Python.

import pickle
datos = {'nombre': 'Ana', 'edad': 28, 'activo': True}
with open('datos.pkl', 'wb') as f:
    pickle.dump(datos, f)

Guardar y leer archivos .pkl

Una vez tenemos serializado el archivo, podemos leerlo para luego deserializar el objeto que habíamos almacenado en disco.

with open('datos.pkl', 'rb') as f:
    datos_recuperados = pickle.load(f)

print(datos_recuperados)

Manejo de errores comunes con Pickle

Hay situaciones en las que Pickle nos puede devolver errores. Vamos a ver cómo se manejan mediante el tratamiento de excepciones de tipo pickle.UnpicklingError, las cuales se producen cuando el archivo está corrupto por algún motivo y Python no puede deserializarlo.

Este ejemplo de código te muestra cómo manejarías la excepción en un bloque try:

try:
    with open('archivo.txt', 'rb') as f:
        pickle.load(f)
except pickle.UnpicklingError as e:
    print('Error al deserializar:', e)

Ventajas de usar Pickle para serializar datos

Pickle es el medio más común para serializar objetos y datos en general en Python. Algunas ventajas las hemos comentado ya, pero vamos a repasar las más destacables.

Compatible con una amplia variedad de tipos de datos

Con Pickle podemos serializar prácticamente cualquier objeto o estructura de datos de Python. Es posible también serializar estructuras complejas, con tantos grados de anidación como sea necesario.

Rápido y eficiente en términos de rendimiento

De manera predeterminada se serializa en un archivo en formato binario, lo que tiene algunas ventajas que ya mencionamos. Además, los protocolos de serialización están optimizados tanto para guardar como para recuperar los datos serializados

No requiere instalación de bibliotecas externas

Como hemos dicho antes, Pickle está incluido en Python, por lo que es fácil de usar y está siempre disponible en cualquier instalación del lenguaje, sin necesidad de librerías adicionales.

Permite múltiples protocolos de serialización

Existen diversos protocolos de serialización, que ofrecen distintos niveles de compatibilidad con objetos y estructuras de datos, así como distintos niveles de rendimiento.

Integración sencilla con archivos y sockets

Podemos usar Pickle en numerosos contextos, como por ejemplo almacenar los datos en archivos de texto, pero también lo podemos usar de manera directa para transferirlos mediante flujos de datos enviados por sockets a través de una red.

Riesgos y limitaciones de Pickle

Aunque el módulo de Pickle es capaz de trabajar en muchos contextos y es compatible con la mayoría de estructuras de datos, podemos encontrar algunas limitaciones que también es importante conocer.

Problemas de seguridad al deserializar

El uso de objetos Pickle puede entrañar problemas de seguridad, sobre todo el paso de la deserialización, cuyos objetos podrían introducir algún código malicioso que podría ejecutarse durante la carga.

No compatible entre diferentes versiones de Python

En algunos casos podría haber incompatibilidades, sobre todo en versiones diferentes de Python. Por ello, un archivo generado con una versión puede no funcionar en otra. Aunque no suele ocurrir habitualmente, podrá pasar en el caso de que haya saltos mayores de versiones del lenguaje.

No apto para compartir datos entre lenguajes

Pickle es un formato específico de Python y no está pensado para compartir datos entre distintos tipos de aplicaciones, desarrolladas en otros lenguajes de programación. Para ello existen otros lenguajes de intercambio de datos más genéricos como JSON o XML.

Alternativas a Pickle en Python

Pickle es la alternativa más común para serializar objetos en Python, por ser muy versátil y además no requerir otras librerías externas. De todos modos, eso no quiere decir que no existan alternativas. Las más importantes son las siguientes:

JSON para objetos simples

JSON es un formato de intercambio de datos muy extendido. Tiene muchas ventajas como ser compatible con la mayoría de lenguajes, ser ligero y fácil de entender por un humano. Es el soporte habitual de los servicios web basados en API REST.

Se trata de un formato útil para serializar datos, es excelente para estructuras sencillas como listas y diccionarios con tipos básicos (cadenas, números, booleanos). Sin embargo, no le podemos pedir mucho más que eso, ya que no es capaz de serializar objetos de una manera inmediata, sino que tendríamos que hacer nosotros mismos las traducciones. Tampoco puedes serializar funciones.

Bibliotecas Marshal y Shelve

Existen dos bibliotecas en Python que ofrecen soporte a la serialización:

  • Marshal consigue ofrecer mejor rendimiento que Pickle, pero la librería está limitada a tipos de datos muy básicos. Se utiliza internamente para almacenar bytecode de Python.
  • Shelve en realidad es un complemento a Pickle que permite almacenar de manera sencilla objetos serializados en una base de datos tipo diccionario, manteniendo persistencia automática.

Protocol Buffers o MessagePack

Luego tenemos dos herramientas existentes en Python y otros lenguajes que pueden ayudarte a serializar, con características un poco más avanzadas que JSON.

  • Protocol Buffers es una tecnología de Google que realiza serialización en binarios que son multiplataforma. Son ideales para sistemas distribuidos que pueden estar escritos en varios lenguajes.
  • MessagePack es un lenguaje similar a JSON pero más compacto y, por tanto, más rápido de transferir. De todos modos, es útil únicamente para transmitir datos ligeros entre distintos lenguajes.

¿Cuándo usar Pickle en tus proyectos Python?

Vamos a ver algunos casos de uso habituales de Pickle en proyectos desarrollados con Python.

Proyectos internos sin intercambio de datos externos

Al tratarse de un formato específico de Python, es perfecto cuando los datos no salen de tu programa y no necesitas compartirlos con sistemas desarrollados en otros lenguajes.

Scripts de análisis de datos o automatización

Gracias a su buen rendimiento se puede usar en proyectos de análisis donde necesitas guardar y cargar rápidamente grandes estructuras de datos.

Desarrollo de prototipos rápidos con persistencia

Si necesitas persistencia de datos ofrece bastante simplicidad, por lo que es aplicable perfectamente cuando quieres probar ideas en prototipos donde no deseas invertir tiempo en diseñar formatos de almacenamiento.

Consideraciones de seguridad al usar Pickle en Python

Antes mencionamos que el uso de Pickle en Python puede no ser seguro. Vamos a ver aspectos relacionados con la seguridad que son importantes de conocer:

Riesgo de ejecución de código malicioso al deserializar

Tienes que tener en cuenta que Pickle podría ejecutar código arbitrario durante la carga de una estructura serializada. De modo que te pueden inyectar código, con el agravante que se corre el riesgo de que esos scripts de código puedan ejecutarse cuando realizas la operación de deserializar.

No es seguro para datos provenientes de fuentes externas

Como decimos, el hecho de poder ejecutar código al deserializar hace delicado el confiar en archivos de Pickle creados por otros desarrolladores o publicados en Internet. Es importante deserializar solamente tus propios archivos Pickle o usar únicamente archivos .pkl de fuentes en las que confíes.

Se recomienda usar alternativas como JSON para datos compartidos

Si deseas compartir datos lo mejor desde el punto de vista de la seguridad es guardarlos en otros formatos más estándar y disponibles en otros lenguajes, como JSON.  JSON es mucho más seguro, al no almacenar más que datos crudos, sin funciones y mucho menos secuencias de código que puedan llegar a ejecutarse durante la deserialización.

Fernán García de Zúñiga

Productos relacionados: