marshal en Python: formato interno

Publicado el: 27/08/2026
Tempo de leitura: 6 minutos
Código binario verde sobre el teclado de un portátil, representando datos internos de Python.

El módulo marshal lee y escribe un formato binario interno utilizado principalmente por Python para almacenar code objects en archivos compilados. Puede representar varios tipos básicos, como números, strings, bytes, tuplas, listas, sets, frozensets, diccionarios y objetos de código, según la versión del intérprete.

Aunque puede parecer una alternativa rápida a JSON o pickle, marshal no fue diseñado como formato general de persistencia. La compatibilidad no está garantizada para todos los tipos, los detalles internos pueden cambiar y nunca deben cargarse datos inválidos o maliciosos. Sus usos apropiados son limitados: tooling de Python, caches descartables, experimentos controlados y estudio de internals.

marshal y archivos .pyc

Cuando Python compila un módulo, puede crear un archivo de bytecode dentro de __pycache__. El archivo incluye un header del sistema de imports y una representación de un code object.

No trates un archivo .pyc completo como un simple resultado de marshal.dumps(). El header contiene metadatos y cambia con el tiempo. Prefiere utilidades de import y herramientas especializadas.

Valores básicos

El formato admite un conjunto seleccionado de tipos nativos.

import marshal

valor = {
    "nombre": "ejemplo",
    "version": 1,
    "items": [1, 2, 3],
}

datos = marshal.dumps(valor)
restaurado = marshal.loads(datos)
print(restaurado)

Un round trip exitoso conserva valores soportados, pero no crea un contrato público estable.

dump y load

dump(value, file) escribe en un stream binario y load(file) lee un objeto.

import marshal

with open("estado.bin", "wb") as archivo:
    marshal.dump(valor, archivo)

with open("estado.bin", "rb") as archivo:
    valor = marshal.load(archivo)

Abre siempre en modo binario. Un stream de texto intenta convertir caracteres y no admite bytes arbitrarios.

dumps y loads

dumps() devuelve bytes y loads() acepta un valor bytes-like.

payload = marshal.dumps((1, 2, 3))
valor = marshal.loads(payload)

Es práctico cuando el almacenamiento, hashing o transporte ya trabaja con bytes.

Versiones del formato

Las funciones de escritura aceptan una versión. El default corresponde al formato recomendado por el intérprete actual.

payload = marshal.dumps(valor, 4)

No selecciones una versión solo porque su número sea mayor. Consulta la documentación del runtime y prueba el destino.

Compatibilidad limitada

Python conserva determinados valores simples entre cambios cuando es posible, pero los code objects no son compatibles entre versiones de Python. Los internals cambian.

Usa un formato documentado y versionado si los datos deben sobrevivir upgrades, cruzar servicios o ser leídos por otro lenguaje.

Code objects

Un code object contiene bytecode, constantes, nombres, variables y metadatos de ejecución.

import marshal

codigo = compile("resultado = 2 + 3", "ejemplo.py", "exec")
payload = marshal.dumps(codigo)
restaurado = marshal.loads(payload)
namespace = {}
exec(restaurado, namespace)
print(namespace["resultado"])

Ejecutar el objeto restaurado ejecuta código. Hazlo solo con datos producidos y protegidos por un sistema confiable.

allow_code

Las APIs actuales ofrecen el parámetro allow_code para controlar si pueden serializarse o deserializarse code objects.

datos = marshal.dumps(valor, allow_code=False)
restaurado = marshal.loads(datos, allow_code=False)

Deshabilitar code objects elimina una categoría de riesgo, pero no vuelve segura la entrada hostil.

Entrada no confiable

La documentación oficial advierte contra cargar datos de fuentes no confiables. Un payload malformado puede provocar fallos, consumo excesivo u otros comportamientos inseguros.

Nunca llames marshal.loads() con requests HTTP, mensajes de queues públicas, uploads o caches compartidos sin una frontera fuerte de confianza.

Protección de integridad

Cuando un archivo interno es importante, protégelo con permisos y, cuando corresponda, MAC o firma criptográfica. La verificación ayuda a detectar alteraciones.

Una firma no resuelve incompatibilidad y solo funciona si clave y productor son confiables.

Limita el tamaño

Comprueba el tamaño antes de leer. Las estructuras grandes consumen memoria y CPU.

from pathlib import Path

ruta = Path("estado.bin")
if ruta.stat().st_size > 10_000_000:
    raise ValueError("archivo demasiado grande")

El límite debe reflejar el caso real.

Profundidad y recursión

Valores muy anidados pueden superar límites internos. No aumentes la recursión solo para aceptar payloads arbitrarios.

Valida la estructura lógica después de la carga y prefiere schemas poco profundos.

Objetos no soportados

Instancias de clases propias, funciones normales, conexiones activas, generators y muchos otros objetos no tienen representación directa.

try:
    marshal.dumps(object())
except ValueError as error:
    print(error)

No construyas una capa compleja solo para forzar el formato. JSON, dataclasses o pickle controlado pueden representar mejor el dominio.

Valores singleton

None, True y False son soportados. Aun así, valida tipo y schema al cargar.

Que un valor pueda representarse no significa que sea válido para la aplicación.

Diccionarios

Los mappings pueden contener claves y valores soportados. El orden observable no debe tratarse como contrato del formato.

La configuración se expresa mejor con un schema explícito y versionado.

Sets

Sets y frozensets pueden representarse según la versión del formato. Como no tienen orden semántico, los bytes no sirven como hash canónico.

Normaliza la estructura según una especificación propia cuando necesites firma determinística.

Números float y complex

El formato admite tipos numéricos de Python, pero no busca interoperabilidad.

Para decimales precisos o dinero portable, serializa strings o enteros bajo un schema explícito.

marshal frente a pickle

Pickle soporta más objetos y customización mediante herramientas como copyreg en Python. Ambos son específicos de Python y no deben recibir entrada no confiable.

marshal es más restringido y está más ligado al intérprete.

marshal frente a JSON

JSON tiene menos tipos, pero es documentado, interoperable y apropiado para APIs con validación.

Usa JSON para datos de aplicación y comunicación. Usa marshal solo cuando los internals de Python sean una necesidad real.

marshal frente a struct

struct empaqueta valores según un layout binario explícito y es mejor para protocolos y archivos estables.

Marshal describe valores Python y no publica un layout pensado para otras implementaciones.

Caches descartables

Un cache creado y consumido por la misma versión puede ser aceptable. El sistema debe poder borrarlo y reconstruirlo tras cualquier error.

Nunca hagas que los datos marshal sean la única copia importante.

Metadatos externos

Guarda junto al payload versión de la aplicación, versión de Python, checksum y timestamp.

metadatos = {
    "python": platform.python_version(),
    "schema": 1,
}

Así puedes rechazar caches incompatibles antes de la carga.

Escritura atómica

Escribe primero en un archivo temporal, realiza flush si importa la durabilidad y sustituye con os.replace().

Un crash durante escritura directa puede dejar un payload truncado.

Acceso concurrente

Varios procesos no deben sobrescribir el mismo archivo sin coordinación. Usa locks, nombres versionados o un servicio de cache.

La sustitución atómica permite que lectores vean la versión anterior o la nueva.

Fallos de lectura

Maneja errores esperados, descarta caches reconstruibles y conserva diagnóstico.

try:
    valor = marshal.loads(payload)
except (EOFError, ValueError, TypeError) as error:
    registrar_cache_invalido(error)
    valor = reconstruir()

No continúes con estado parcialmente leído.

Auditoría

Las operaciones pueden emitir eventos de auditoría de Python. Entornos controlados pueden observar carga de objetos y code objects.

Los audit hooks complementan permisos y aislamiento.

Análisis de bytecode

Para estudiar code objects, combina compile(), marshal controlado y el módulo dis. Nunca ejecutes bytecode desconocido.

ast en Python explica una capa estructural anterior.

Tests entre versiones

Si un cache cruza deployments, prueba cada versión soportada. Incluye lectura antigua, rechazo de incompatible y reconstrucción automática.

Un round trip en el mismo proceso no es suficiente.

Observabilidad

Registra tamaño, versión de aplicación, versión de Python, duración y motivo de invalidación. No guardes bytes crudos.

Errores comunes

Los fallos frecuentes son usar marshal como base de datos, leer payload externo, asumir compatibilidad de code objects, tratar un .pyc como payload puro, ejecutar código sin confianza, omitir límites y mantener información importante solo en este formato.

Conclusión

marshal es una herramienta interna de Python apropiada para code objects y caches descartables bajo control estricto. Usa streams binarios, valida tamaño y versiones, protege el origen y reconstruye caches incompatibles.

Para datos de aplicación, prefiere formatos estables y schemas explícitos. Consulta la documentación oficial de marshal y la documentación de dis.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Código Python asíncrono en un portátil para inspect.markcoroutinefunction
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    markcoroutinefunction: detecta wrappers async

    Aprende inspect.markcoroutinefunction en Python para identificar wrappers asíncronos, integrar frameworks y evitar detecciones incorrectas.

    Ler mais

    Tempo de leitura: 5 minutos
    10/10/2026
    Código Python para recorrer carpetas y archivos con Path.walk
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    Path.walk: recorre directorios con seguridad

    Aprende Path.walk en Python para recorrer directorios, filtrar archivos, tratar errores y controlar la travesía con seguridad.

    Ler mais

    Tempo de leitura: 5 minutos
    10/10/2026
    Depuración de un proceso Python en terminal con código
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pdb -p: depura procesos Python en ejecución

    Aprende a conectar pdb a un proceso Python en ejecución, inspeccionar la pila y diagnosticar bloqueos de forma segura.

    Ler mais

    Tempo de leitura: 6 minutos
    09/10/2026
    Código Python para representar fracciones exactas
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    fractions.from_number: convierte números en fracciones

    Aprende fractions.from_number en Python para convertir números en fracciones exactas, controlar precisión, validar entradas y evitar redondeos inesperados.

    Ler mais

    Tempo de leitura: 4 minutos
    09/10/2026
    Desarrollador configurando un servidor HTTPS y certificado TLS con Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    HTTPSServer: crea un servidor HTTPS local en Python

    Aprende HTTPSServer en Python para crear servicios HTTPS locales, configurar certificados, usar hilos y comprender sus límites.

    Ler mais

    Tempo de leitura: 4 minutos
    08/10/2026
    Archivos protegidos que representan extracción segura de TAR con Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    tarfile extraction_filter: extrae TAR con seguridad

    Aprende tarfile extraction_filter en Python para extraer archivos TAR con validación, seguridad y control de rutas.

    Ler mais

    Tempo de leitura: 6 minutos
    08/10/2026