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

    Detailed shot of a Jungle Carpet Python (Morelia spilota cheynei) in its natural habitat.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    zlib en Python: comprime datos

    Aprende zlib en Python para comprimir y descomprimir bytes, procesar streams, usar checksums y limitar datos externos.

    Ler mais

    Tempo de leitura: 6 minutos
    16/08/2026
    Diagrama de archivos y sistema que representa configuración INI con configparser en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    configparser en Python: archivos INI

    Aprende configparser en Python para leer y escribir archivos INI, combinar defaults, usar interpolación y actualizar de forma segura.

    Ler mais

    Tempo de leitura: 5 minutos
    16/08/2026
    Módulo de memoria RAM que representa gestión de objetos con gc en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    gc en Python: controla el recolector

    Aprende gc en Python para controlar la recolección cíclica, inspeccionar objetos, diagnosticar memoria y observar pausas.

    Ler mais

    Tempo de leitura: 7 minutos
    16/08/2026
    Líneas de código fuente que representan rastreo de ejecución con trace en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    trace en Python: rastrea ejecución

    Aprende trace en Python para contar líneas, seguir la ejecución, listar funciones, combinar cobertura y filtrar módulos.

    Ler mais

    Tempo de leitura: 6 minutos
    16/08/2026
    Portátil con gráficos de rendimiento que representa análisis de perfiles con pstats en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pstats en Python: analiza perfiles

    Aprende pstats en Python para ordenar, filtrar, combinar e interpretar perfiles de cProfile, callers, callees y tiempos acumulados.

    Ler mais

    Tempo de leitura: 5 minutos
    15/08/2026
    Portátil con código que representa ejemplos ejecutables probados con doctest en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    doctest en Python: prueba ejemplos

    Aprende doctest en Python para ejecutar ejemplos en docstrings y archivos, normalizar salidas e integrar documentación con CI.

    Ler mais

    Tempo de leitura: 5 minutos
    15/08/2026