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

    Vibrant assortment of pickled vegetables in jars with red fabric covers, displayed on shelves.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    copyreg en Python: personaliza pickle

    Aprende copyreg en Python para personalizar pickle, registrar reducers, versionar estado, evitar conflictos globales y serializar con seguridad.

    Ler mais

    Tempo de leitura: 6 minutos
    27/08/2026
    A developer typing code on a laptop with a Python book beside in an office.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    reprlib en Python: objetos resumidos

    Aprende reprlib en Python para resumir listas, strings y objetos recursivos, limitar logs y crear representaciones seguras y legibles.

    Ler mais

    Tempo de leitura: 6 minutos
    27/08/2026
    Close-up view of a computer screen displaying code in a software development environment.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    graphlib en Python: orden topológico

    Aprende graphlib en Python para ordenar dependencias, detectar ciclos, ejecutar tareas listas en paralelo y crear pipelines seguros.

    Ler mais

    Tempo de leitura: 7 minutos
    27/08/2026
    Close-up view of a computer screen displaying code in a software development environment.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    weakref: evita retener objetos en cachés

    Aprende weakref en Python para referencias débiles, caches, WeakSet, WeakMethod, finalize, callbacks y evitar retención accidental.

    Ler mais

    Tempo de leitura: 7 minutos
    27/08/2026
    A top view of stacked timber logs showcasing natural textures and patterns.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    contextlib en Python: gestiona recursos

    Aprende contextlib en Python con contextmanager, ExitStack, suppress, closing, asynccontextmanager y cleanup seguro de recursos.

    Ler mais

    Tempo de leitura: 7 minutos
    27/08/2026
    Close-up of a computer screen displaying colorful programming code with depth of field.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    ast en Python: analiza código fuente

    Aprende ast en Python para analizar y transformar código, crear visitors, conservar posiciones, usar literal_eval y evitar riesgos de ejecución.

    Ler mais

    Tempo de leitura: 6 minutos
    27/08/2026