O módulo lzma no Python oferece compressão e descompressão com os algoritmos LZMA e LZMA2. Ele trabalha com arquivos .xz, com o formato legado .lzma e com streams brutos configurados por filtros. A interface inclui funções de uma etapa, objetos incrementais e uma API de arquivo muito parecida com bz2.
LZMA costuma produzir resultados menores que gzip e bzip2 em muitos conjuntos de dados, mas exige mais CPU e pode consumir bastante memória. O preset 9, por exemplo, pode levar o compressor a centenas de megabytes de overhead. Portanto, a escolha deve ser medida com dados reais, e o preset padrão 6 costuma ser um ponto de partida mais seguro.
Quando usar lzma
Use lzma quando o formato XZ for obrigatório, quando tamanho final tiver prioridade e quando o ambiente puder pagar o custo de compressão. Para arquivos que precisam ser abertos rapidamente ou por muitos programas, gzip pode ser mais prático. Para comparar outro algoritmo eficiente em texto, veja bz2 no Python.
Comprima dados em memória
import lzma
dados = ("registro de auditoria\n" * 2000).encode("utf-8")
compactado = lzma.compress(dados, preset=6)
restaurado = lzma.decompress(compactado)
assert restaurado == dados
print(len(dados), len(compactado))lzma.compress() usa FORMAT_XZ por padrão. A função é conveniente para cargas pequenas, mas mantém entrada e saída em memória. Em volumes grandes, use lzma.open() ou processamento incremental.
Grave arquivos .xz em modo texto
import lzma
with lzma.open("eventos.log.xz", "wt", encoding="utf-8", preset=6) as arquivo:
arquivo.write("início do processo\n")
arquivo.write("processamento concluído\n")Os modos seguem a convenção de open(): rt, wt, xt e at para texto; rb, wb, xb e ab para binário. Use x quando a sobrescrita acidental precisa ser bloqueada.
Leia sem carregar tudo
import lzma
with lzma.open("eventos.log.xz", "rt", encoding="utf-8") as arquivo:
for linha in arquivo:
processar(linha.rstrip())A iteração entrega uma linha por vez e combina bem com as técnicas do guia para ler arquivos gigantes. Mesmo assim, a descompressão mantém estado e dicionário internos; monitore memória em processos longos.
Use LZMAFile quando precisar de binário
LZMAFile aceita um caminho ou um arquivo já aberto. Ele implementa a maior parte de io.BufferedIOBase, suporta with, iteração, leitura, escrita e busca quando o fluxo subjacente permite.
from lzma import LZMAFile
with LZMAFile("pacote.bin.xz", "wb", preset=5) as destino:
destino.write(b"cabecalho\x00")
destino.write(b"dados" * 10_000)Uma única instância não é segura para leitores ou escritores simultâneos. Se várias threads precisarem acessar o mesmo recurso, use um lock ou instâncias independentes.
Escolha o formato correto
FORMAT_XZ: formato moderno, com checks de integridade e suporte a filtros.FORMAT_ALONE: formato legado.lzma, mais limitado.FORMAT_RAW: stream sem contêiner; exige a cadeia de filtros na compressão e na descompressão.FORMAT_AUTO: usado para detectar XZ ou LZMA durante a leitura.
Para novos arquivos, prefira XZ. RAW é adequado apenas quando um protocolo externo define todos os parâmetros.
Checks de integridade
O contêiner XZ pode usar CHECK_CRC32, CHECK_CRC64 ou CHECK_SHA256. O padrão é CRC64. Use lzma.is_check_supported() antes de selecionar uma opção que pode não existir na liblzma instalada.
import lzma
check = lzma.CHECK_SHA256
if not lzma.is_check_supported(check):
check = lzma.CHECK_CRC64
resultado = lzma.compress(b"conteudo", check=check)Esses checks detectam corrupção acidental. Eles não substituem assinatura digital, autenticação ou hash protegido contra adulteração.
Compressão incremental
import lzma
compressor = lzma.LZMACompressor(preset=6)
partes = []
for bloco in gerar_blocos():
trecho = compressor.compress(bloco)
if trecho:
partes.append(trecho)
partes.append(compressor.flush())
compactado = b"".join(partes)O objeto pode armazenar dados internamente, portanto uma chamada pode retornar vazio. flush() finaliza o stream e torna o compressor inutilizável.
Limite memória na descompressão
LZMADecompressor aceita memlimit. Se o stream exigir mais memória do que o permitido, a operação falha com LZMAError. Isso é uma proteção importante para conteúdo externo.
import lzma
dec = lzma.LZMADecompressor(memlimit=128 * 1024 * 1024)
saida = bytearray()
limite_saida = 50 * 1024 * 1024
for bloco in receber_blocos():
pendente = bloco
while pendente or not dec.needs_input:
parte = dec.decompress(pendente, max_length=64 * 1024)
pendente = b""
saida.extend(parte)
if len(saida) > limite_saida:
raise ValueError("saída descompactada excedeu o limite")
if dec.eof:
breakmemlimit limita a memória do descompressor, mas não limita sozinho o tamanho final. Use também max_length e um contador total.
Streams concatenados
lzma.decompress() e LZMAFile processam múltiplos streams concatenados. Uma instância de LZMADecompressor não faz isso automaticamente. Ao atingir eof, examine unused_data e crie outro objeto se o formato permitir membros adicionais.
Filtros personalizados
Uma cadeia pode ter até quatro filtros, terminando obrigatoriamente em LZMA1 ou LZMA2. O filtro delta pode melhorar dados numéricos com diferenças regulares; filtros BCJ ajudam código de máquina.
import lzma
filtros = [
{"id": lzma.FILTER_DELTA, "dist": 4},
{"id": lzma.FILTER_LZMA2, "preset": 6},
]
compactado = lzma.compress(dados, format=lzma.FORMAT_RAW, filters=filtros)Filtros customizados aumentam a complexidade e prejudicam interoperabilidade. Documente exatamente a cadeia e teste com outras implementações.
Evite presets extremos por padrão
PRESET_EXTREME pode ser combinado com níveis de 0 a 9, mas normalmente aumenta muito o tempo para uma melhoria modesta. Não use 9 extremo em uma API web sem benchmark, limite de memória e fila de trabalho controlada.
Segurança operacional
- Imponha limite ao arquivo comprimido.
- Use
memlimite limite total de saída. - Valide
eofpara detectar truncamento. - Não confie em extensão ou nome fornecido.
- Armazene em diretório isolado.
- Limite tempo de CPU.
- Não compartilhe a instância entre threads.
Se o XZ vier dentro de um pacote com vários caminhos, aplique também as regras do guia de arquivos ZIP com Python.
Teste com dados representativos
Meça tempo, memória e tamanho com textos, binários, dados já comprimidos e arquivos vazios. Inclua entradas corrompidas, truncadas, vários membros e checks diferentes. Compare presets 3, 6 e 9 antes de decidir.
Boas práticas
- Prefira
FORMAT_XZem projetos novos. - Mantenha o preset padrão até medir.
- Use modo texto com codificação explícita.
- Use
withpara fechar arquivos. - Processe grandes volumes incrementalmente.
- Finalize o compressor com
flush(). - Combine
memlimitcom limite de saída. - Trate
LZMAErrorsem expor dados sensíveis.
Conclusão
O lzma no Python fornece compressão XZ eficiente, arquivos em texto ou binário, checks de integridade e filtros avançados. Sua principal vantagem é a taxa de compressão; seus principais custos são CPU, memória e maior complexidade operacional.
Consulte a documentação oficial do lzma e a página do XZ Utils. Para configurar limites e presets por ambiente, veja configparser no Python.







