bz2 en Python: comprime con bzip2

Publicado el: 16/08/2026
Tempo de leitura: 4 minutos
A close-up shot showcasing the intricate scales of a snake, highlighting texture and color.

El módulo bz2 en Python comprime y descomprime datos con el algoritmo bzip2 sin instalar paquetes externos. Sirve para operaciones pequeñas en memoria, archivos comprimidos, texto con codificación y streams incrementales procesados por bloques.

Bzip2 suele producir archivos menores que gzip en textos repetitivos, aunque normalmente consume más CPU. La elección correcta depende del tamaño, la velocidad, la compatibilidad y la frecuencia de acceso. Esta guía explica las APIs principales y los controles necesarios cuando los datos comprimidos provienen de fuentes externas.

Cuándo usar bz2

Usa bz2 cuando un flujo existente requiera archivos .bz2, cuando la tasa de compresión sea más importante que la velocidad máxima o cuando intercambies logs y datasets con herramientas Unix. Para una interfaz DEFLATE de nivel inferior, consulta zlib en Python.

Compresión directa en memoria

bz2.compress() recibe bytes y devuelve bytes comprimidos. Los niveles van de 1 a 9. Un valor alto favorece el tamaño, pero puede tardar más.

import bz2

datos = ("fila del informe\n" * 1000).encode("utf-8")
comprimido = bz2.compress(datos, compresslevel=9)
restaurado = bz2.decompress(comprimido)

assert restaurado == datos
print(len(datos), len(comprimido))

La solución es sencilla, pero mantiene entrada y salida completas en memoria. Para volúmenes grandes, utiliza archivos o clases incrementales. La guía para leer archivos gigantes con Python presenta técnicas complementarias para controlar la RAM.

Escribe un archivo .bz2

bz2.open() se parece a open(). Los modos binarios reciben bytes y los modos de texto requieren una codificación explícita.

import bz2

with bz2.open("informe.csv.bz2", "wt", encoding="utf-8") as archivo:
    archivo.write("producto,cantidad\n")
    archivo.write("teclado,12\n")
    archivo.write("monitor,4\n")

wt reemplaza el destino. Usa xt para fallar si el archivo ya existe. El modo append agrega otro stream comprimido al final; BZ2File puede leer streams concatenados.

Lee línea por línea

import bz2

with bz2.open("informe.csv.bz2", "rt", encoding="utf-8") as archivo:
    for numero, linea in enumerate(archivo, start=1):
        print(numero, linea.rstrip())

La iteración evita cargar todo el texto. Captura UnicodeDecodeError cuando la codificación sea incierta. Evita errors="ignore" como solución automática porque puede eliminar caracteres y corromper datos silenciosamente.

Trabaja con BZ2File

BZ2File funciona en modo binario y acepta una ruta o un objeto de archivo existente. Implementa gran parte de io.BufferedIOBase.

from bz2 import BZ2File
from pathlib import Path

ruta = Path("datos.bin.bz2")
with BZ2File(ruta, "wb", compresslevel=7) as destino:
    destino.write(b"cabecera\x00")
    destino.write(b"contenido" * 500)

La clase admite context manager, iteración, búsqueda cuando está disponible, read1() y readinto(). Una misma instancia no es segura para lecturas o escrituras simultáneas. Entrega un objeto independiente a cada tarea o protege el acceso.

Compresión incremental

BZ2Compressor es apropiado cuando los datos llegan por bloques. compress() puede devolver bytes o una salida vacía porque mantiene buffers internos. Finaliza con flush().

import bz2

compresor = bz2.BZ2Compressor(compresslevel=6)
partes = []

for bloque in generar_bloques():
    salida = compresor.compress(bloque)
    if salida:
        partes.append(salida)

partes.append(compresor.flush())
resultado = b"".join(partes)

Después de flush(), el objeto no puede reutilizarse. Crea uno nuevo para cada stream independiente.

Descompresión incremental limitada

BZ2Decompressor.decompress() acepta max_length. Esto limita la salida por llamada y ayuda a proteger servicios contra expansiones inesperadas.

import bz2

dec = bz2.BZ2Decompressor()
salida = bytearray()
limite = 20_000_000

for bloque in recibir_bloques():
    pendiente = bloque
    while pendiente or not dec.needs_input:
        parte = dec.decompress(pendiente, max_length=64 * 1024)
        pendiente = b""
        salida.extend(parte)
        if len(salida) > limite:
            raise ValueError("el contenido excedió el límite")
        if dec.eof:
            break

Si needs_input es falso, todavía existe salida disponible sin nueva entrada. unused_data guarda bytes posteriores al final. A diferencia de bz2.decompress() y BZ2File, una instancia incremental no continúa automáticamente por varios streams concatenados.

Verifica el final

No consideres válido un archivo solo porque produjo algunos bytes. Comprueba eof para distinguir un stream completo de uno truncado. Maneja OSError, EOFError y los errores de validación de tu aplicación.

Protege el sistema de datos hostiles

La compresión no autentica el contenido. Limita el tamaño comprimido, el tamaño expandido, el tiempo de CPU y la cantidad de etapas. Guarda archivos en un directorio controlado, normaliza nombres y no confíes en la extensión. Para contenedores con rutas, aplica las prácticas de seguridad del artículo sobre archivos ZIP con Python.

Elige el nivel adecuado

El nivel 9 es el predeterminado, no una respuesta universal. Mide con datos reales. Los niveles 5 o 6 pueden ofrecer un mejor equilibrio en pipelines frecuentes. JPEG, MP4 y muchos PDF ya están comprimidos, por lo que bzip2 suele ahorrar poco.

Compara algoritmos

  • gzip: normalmente más rápido y compatible.
  • bz2: eficaz para texto y datos históricos.
  • lzma: puede reducir más el tamaño con mayor coste.
  • zlib: útil para protocolos y streams DEFLATE.

Para backups de directorios, TAR agrupa elementos antes de comprimir. Mantén serialización, archivado y compresión como decisiones separadas.

Prueba ida y vuelta

Un test esencial comprime, descomprime y compara los bytes exactos. Incluye datos vacíos, Unicode codificado, contenido aleatorio, contenido repetitivo, streams truncados, niveles distintos y miembros concatenados.

import bz2
import pytest

@pytest.mark.parametrize("datos", [b"", b"abc", b"x" * 100_000])
def test_round_trip(datos):
    assert bz2.decompress(bz2.compress(datos)) == datos

Buenas prácticas

  • Especifica la codificación en modo texto.
  • Usa with para cerrar archivos.
  • Procesa por bloques cuando el volumen sea grande.
  • Llama a flush() una sola vez.
  • Comprueba eof en entradas parciales.
  • Limita la salida descomprimida.
  • No compartas una instancia entre hilos.
  • Mide con cargas reales.

Conclusión

bz2 en Python proporciona funciones directas, archivos comprimidos, texto e interfaces incrementales para bzip2. La API es clara, pero un sistema robusto debe controlar memoria, límites de stream, miembros concatenados y expansión de contenido no confiable.

Consulta la documentación oficial de bz2 y el proyecto bzip2. Para configuraciones de tareas de compresión, revisa configparser en Python, y para rastrear la ejecución consulta trace en Python.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    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
    Código Python mostrando avisos controlados con catch_warnings
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    catch_warnings: captura warnings en pruebas Python

    Aprende catch_warnings en Python para capturar, probar y controlar avisos con filtros específicos y alcance seguro.

    Ler mais

    Tempo de leitura: 5 minutos
    07/10/2026
    Código Python que representa referencias persistentes de pickle
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pickle persistent_id: serializa referencias externas

    Aprende pickle persistent_id en Python para referencias externas estables, validación, seguridad, rendimiento y compatibilidad.

    Ler mais

    Tempo de leitura: 5 minutos
    07/10/2026
    Código binario que representa buffers y vistas de memoria en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    memoryview.count: cuenta valores sin copiar buffers

    Aprende memoryview.count en Python para contar bytes y valores en buffers sin copias, con formatos, límites y buenas prácticas.

    Ler mais

    Tempo de leitura: 6 minutos
    06/10/2026
    Código Python y anotaciones de tipos
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    annotationlib: evita imports circulares en anotaciones

    Aprende annotationlib en Python para inspeccionar anotaciones diferidas, evitar imports circulares y crear herramientas seguras.

    Ler mais

    Tempo de leitura: 6 minutos
    06/10/2026