marshal no Python: formato interno

Publicado em: 27/08/2026
Tempo de leitura: 8 minutos
A person typing on a laptop with a Python programming book visible, capturing technology and learning.

O módulo marshal lê e grava um formato binário interno usado principalmente pelo próprio Python para armazenar objetos de código em arquivos compilados. Ele consegue representar vários tipos básicos, como números, strings, bytes, tuplas, listas, sets, frozensets, dicionários e code objects, conforme a versão do interpretador.

Apesar de parecer uma alternativa rápida a JSON ou pickle, marshal não foi projetado como formato geral de persistência. A compatibilidade entre versões não é garantida para todos os tipos, o formato pode mudar e dados inválidos ou maliciosos não devem ser carregados. Seu uso ideal é restrito a ferramentas internas, experimentos controlados e compreensão da infraestrutura do Python.

marshal e arquivos .pyc

Quando um módulo Python é compilado, o interpretador cria um arquivo de bytecode em __pycache__. O conteúdo inclui um header gerenciado pela infraestrutura de import e uma representação do code object.

Não trate um arquivo .pyc inteiro como se fosse apenas o resultado de marshal.dumps(). O header contém metadados e pode mudar. Para ler bytecode, prefira ferramentas de import e módulos especializados.

Tipos básicos

O formato suporta um conjunto de tipos do próprio Python. Um exemplo simples:

import marshal

objeto = {
    "nome": "exemplo",
    "versao": 1,
    "valores": [1, 2, 3],
}

dados = marshal.dumps(objeto)
restaurado = marshal.loads(dados)
print(restaurado)

O round trip preserva valores suportados, mas não transforma o formato em contrato público estável.

dump e load

dump(value, file) grava em um arquivo binário e load(file) lê um objeto.

import marshal

with open("estado.bin", "wb") as arquivo:
    marshal.dump(objeto, arquivo)

with open("estado.bin", "rb") as arquivo:
    objeto = marshal.load(arquivo)

Abra sempre em modo binário. Um stream de texto tenta converter bytes e falha.

dumps e loads

dumps() devolve bytes, enquanto loads() recebe um objeto bytes-like.

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

Use essa forma quando o armazenamento, hash ou transporte já trabalha com bytes.

Versão do formato

A função de gravação aceita uma versão do formato. O valor padrão corresponde ao formato atual recomendado pelo interpretador.

payload = marshal.dumps(objeto, 4)

Não escolha uma versão apenas por ser numericamente maior. Consulte a documentação do Python executado e teste leitura no ambiente de destino.

Compatibilidade não é garantia de API

O Python tenta manter determinados valores simples legíveis entre versões de formato, mas code objects não são compatíveis entre versões do interpretador. Detalhes internos podem mudar.

Se os dados precisam sobreviver a upgrades, ser compartilhados entre serviços ou lidos por outra linguagem, use um formato documentado e versionado.

Code objects

Um code object representa bytecode, constantes, nomes, variáveis e metadados de execução de uma função ou módulo.

import marshal

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

Executar o objeto restaurado executa código. Faça isso somente com dados produzidos e protegidos pelo próprio sistema.

allow_code

Nas APIs atuais, o parâmetro allow_code permite controlar se code objects podem ser serializados ou desserializados.

dados = marshal.dumps(objeto, allow_code=False)
valor = marshal.loads(dados, allow_code=False)

Desabilitar code objects reduz uma categoria de risco, mas não transforma entrada hostil em segura.

Dados não confiáveis

A documentação alerta para não carregar dados recebidos de fonte não confiável. Um payload inválido pode provocar comportamento indefinido, falha, consumo excessivo ou outros problemas.

Não use marshal.loads() em request HTTP, mensagem de fila pública, upload de usuário ou cache compartilhado sem uma fronteira forte de confiança.

Assinatura e integridade

Quando o formato é usado internamente, proteja o arquivo com permissões e, quando necessário, assinatura ou MAC. Verificar integridade ajuda a detectar alteração.

A assinatura não resolve incompatibilidade de versão e só é confiável se a chave e o emissor estiverem protegidos.

Limite de tamanho

Antes de ler, verifique o tamanho do arquivo ou mensagem. Estruturas grandes podem consumir memória e CPU.

from pathlib import Path

caminho = Path("estado.bin")
if caminho.stat().st_size > 10_000_000:
    raise ValueError("arquivo grande demais")

O limite deve refletir o caso real da aplicação.

Profundidade e recursão

Estruturas muito profundas podem exceder limites internos ou provocar erros. Não aumente limites de recursão apenas para aceitar payloads arbitrários.

Valide a estrutura lógica após a leitura e prefira dados rasos.

Tipos não suportados

Objetos de classes personalizadas, funções comuns, conexões, generators e muitos outros tipos não possuem representação marshal direta.

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

Não crie um sistema complexo de conversão apenas para forçar o uso do formato. JSON, dataclasses ou pickle controlado podem expressar melhor o domínio.

None e valores singleton

Valores como None, True e False são suportados. Após a carga, mantenha validações de tipo e schema.

O fato de o formato conseguir representar um valor não significa que ele seja válido para a aplicação.

Dicionários

Mappings serializados podem conter chaves e valores suportados. A ordem observável não deve ser usada como contrato do formato.

Para dados de configuração, prefira um schema explícito com nomes, tipos e versões.

Sets

Sets e frozensets podem ser suportados conforme o formato. Como não possuem ordem semântica, bytes gerados não devem ser usados como hash canônico de conteúdo.

Para assinatura determinística de dados, normalize a estrutura antes com uma especificação própria.

Floats e números complexos

O formato suporta tipos numéricos do Python, mas interoperabilidade com outra linguagem não é objetivo.

Se valores monetários ou decimais precisam de precisão e portabilidade, serialize strings ou inteiros segundo um schema explícito, em vez de depender de representação interna.

marshal versus pickle

Pickle suporta uma variedade maior de objetos e mecanismos de customização, como copyreg no Python. Ambos são formatos específicos do Python e não devem receber dados não confiáveis.

marshal é mais restrito e orientado ao interpretador, especialmente a code objects.

marshal versus JSON

JSON possui tipos mais limitados, mas é documentado, interoperável e adequado a APIs quando combinado com validação.

Use JSON para dados de negócio e comunicação. Use marshal apenas quando a ligação com internals do Python for uma exigência real.

marshal versus struct

struct empacota valores binários conforme um layout explícito. É melhor para protocolos e arquivos cujo formato precisa ser estável.

Marshal descreve objetos Python e não oferece um layout público apropriado para outras implementações.

Cache temporário

Um cache descartável criado e consumido pela mesma versão do Python pode ser um caso aceitável. O sistema deve conseguir apagar e reconstruir o cache quando a leitura falhar.

Nunca torne dados marshal a única cópia de informação importante.

Inclua metadados externos

Quando você controla um arquivo interno, guarde fora do payload a versão da aplicação, versão do Python, checksum e timestamp.

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

Esses dados ajudam a rejeitar caches incompatíveis antes da carga.

Escrita atômica

Grave primeiro em um arquivo temporário, faça flush quando necessário e substitua o destino com os.replace().

Uma interrupção durante escrita direta pode deixar um payload truncado que falhará depois.

Concorrência

Vários processos não devem sobrescrever o mesmo arquivo sem coordenação. Use locks, nomes por versão ou um sistema de cache apropriado.

Uma leitura simultânea durante substituição atômica normalmente vê a versão antiga ou nova, não um arquivo parcialmente escrito.

Erros de leitura

Capture erros esperados, descarte caches reconstruíveis e preserve diagnóstico.

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

Não continue com estado parcialmente lido.

Auditoria

Operações de marshal podem emitir eventos de auditoria do Python. Ambientes controlados podem monitorar carga de objetos e code objects.

Audit hooks complementam isolamento e permissões, não os substituem.

Análise de bytecode

Para estudar code objects, combine compile(), marshal em ambiente controlado e o módulo dis. Não execute bytecode desconhecido.

O artigo sobre ast no Python mostra uma camada estrutural anterior ao bytecode.

Testes entre versões

Se um cache atravessa deployments, execute uma matriz com as versões de Python suportadas. Teste leitura de arquivo antigo, rejeição de incompatível e reconstrução automática.

Não confie apenas no round trip dentro do mesmo processo.

Observabilidade

Registre tamanho, versão da aplicação, versão do Python, duração e motivo da invalidação. Não registre os bytes completos, que podem conter código ou dados sensíveis.

Erros comuns

Os erros mais frequentes são usar marshal como banco de dados, ler payload externo, presumir compatibilidade de code objects, tratar .pyc como payload puro, executar code object restaurado sem confiança, omitir limites e manter somente uma cópia importante no formato.

Conclusão

marshal é uma ferramenta interna do ecossistema Python, adequada a code objects e caches descartáveis sob controle estrito. Use arquivos binários, valide tamanho e versão, proteja origem e reconstrua o cache quando houver incompatibilidade.

Para dados de aplicação, prefira formatos estáveis e schemas explícitos. Consulte a documentação oficial de marshal e a documentação de dis.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Rack de servidores representando balanceamento de conexões com SO_REUSEPORT_LB no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    SO_REUSEPORT_LB: distribua conexões entre workers

    Aprenda SO_REUSEPORT_LB no Python para distribuir conexões entre múltiplos workers com segurança, testes e portabilidade.

    Ler mais

    Tempo de leitura: 6 minutos
    11/10/2026
    Código Python assíncrono em notebook para inspect.markcoroutinefunction
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    markcoroutinefunction: identifique wrappers async

    Aprenda inspect.markcoroutinefunction no Python para identificar wrappers assíncronos, integrar frameworks e evitar detecção incorreta de corrotinas.

    Ler mais

    Tempo de leitura: 6 minutos
    10/10/2026
    Código Python para percorrer pastas e arquivos com Path.walk
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    Path.walk: percorra diretórios com segurança

    Aprenda Path.walk no Python para percorrer diretórios, filtrar arquivos, tratar erros e controlar a travessia com segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    10/10/2026
    Depuração de processo Python em terminal com código
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    pdb -p: depure processos Python em execução

    Aprenda a anexar o pdb a um processo Python em execução, inspecionar pilhas e diagnosticar travamentos com segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    09/10/2026
    Código Python e representação de frações numéricas
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    fractions.from_number: converta números em frações

    Aprenda fractions.from_number no Python para converter números em frações exatas, controlar precisão e evitar arredondamentos inesperados.

    Ler mais

    Tempo de leitura: 5 minutos
    09/10/2026
    Desenvolvedor configurando servidor HTTPS e certificado TLS com Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    HTTPSServer: crie servidor HTTPS local no Python

    Aprenda HTTPSServer no Python para servir HTTPS localmente, configurar certificados, usar threads e entender limites de segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    08/10/2026