Cómo crear archivos ZIP con Python y zipfile

Publicado el: 11/07/2026
Tempo de leitura: 4 minutos
Compactando arquivos ZIP automaticamente com Python

Crear archivos ZIP con Python es útil para generar copias de seguridad, agrupar informes, comprimir carpetas y preparar paquetes para envío. La biblioteca estándar incluye el módulo zipfile, por lo que no necesitas instalar dependencias externas para trabajar con el formato ZIP.

Para ampliar conceptos, consulta las guías sobre archivos en Python, función zip(), manejo de excepciones, logging y automatización. Como referencias externas, revisa la documentación oficial de zipfile y la documentación oficial de pathlib.

Crear un ZIP con un archivo

from zipfile import ZipFile, ZIP_DEFLATED

with ZipFile("documentos.zip", "w", compression=ZIP_DEFLATED) as archivo_zip:
    archivo_zip.write("informe.pdf")

El modo w crea un archivo nuevo y reemplaza uno existente con el mismo nombre. ZIP_DEFLATED activa compresión mediante Deflate.

Controlar el nombre interno

Sin indicar otra cosa, write() puede guardar la ruta proporcionada. Usa arcname para definir el nombre dentro del ZIP:

archivo_zip.write(
    "salida/informe.pdf",
    arcname="informe.pdf",
)

Esto evita incluir carpetas locales que no deberían aparecer para el destinatario.

Añadir varios archivos

from pathlib import Path
from zipfile import ZipFile, ZIP_DEFLATED

archivos = [
    Path("informe.pdf"),
    Path("resumen.csv"),
    Path("grafico.png"),
]

with ZipFile("entrega.zip", "w", compression=ZIP_DEFLATED) as archivo_zip:
    for ruta in archivos:
        archivo_zip.write(ruta, arcname=ruta.name)

Antes de comprimir, valida que cada ruta exista y sea un archivo.

Comprimir una carpeta completa

from pathlib import Path
from zipfile import ZipFile, ZIP_DEFLATED

origen = Path("proyecto")
destino = Path("proyecto.zip")

with ZipFile(destino, "w", compression=ZIP_DEFLATED) as archivo_zip:
    for ruta in origen.rglob("*"):
        if ruta.is_file():
            nombre_interno = ruta.relative_to(origen)
            archivo_zip.write(ruta, arcname=nombre_interno)

relative_to() conserva la estructura interna sin incluir el camino completo del ordenador.

Excluir archivos innecesarios

IGNORAR_CARPETAS = {".git", ".venv", "__pycache__"}
IGNORAR_EXTENSIONES = {".pyc", ".log"}

for ruta in origen.rglob("*"):
    if not ruta.is_file():
        continue
    if any(parte in IGNORAR_CARPETAS for parte in ruta.parts):
        continue
    if ruta.suffix.lower() in IGNORAR_EXTENSIONES:
        continue

    archivo_zip.write(ruta, arcname=ruta.relative_to(origen))

No incluyas entornos virtuales, repositorios Git, cachés ni secretos salvo que exista una razón clara.

Evitar incluir el ZIP dentro de sí mismo

Si el archivo de destino se crea dentro de la carpeta de origen, rglob() puede encontrarlo mientras se escribe. Guarda el destino fuera de la carpeta o exclúyelo explícitamente:

if ruta.resolve() == destino.resolve():
    continue

Añadir archivos a un ZIP existente

with ZipFile("entrega.zip", "a", compression=ZIP_DEFLATED) as archivo_zip:
    archivo_zip.write("notas.txt", arcname="notas.txt")

El modo a conserva el contenido anterior. Ten cuidado con nombres duplicados, porque pueden existir varias entradas con el mismo nombre dentro del ZIP.

Escribir contenido sin archivo temporal

from zipfile import ZipFile, ZIP_DEFLATED

with ZipFile("datos.zip", "w", compression=ZIP_DEFLATED) as archivo_zip:
    archivo_zip.writestr("estado.txt", "Proceso completado\n")

writestr() resulta útil para informes pequeños, configuraciones generadas o manifiestos.

Crear un CSV dentro del ZIP

import csv
import io
from zipfile import ZipFile, ZIP_DEFLATED

buffer = io.StringIO()
escritor = csv.writer(buffer)
escritor.writerow(["producto", "cantidad"])
escritor.writerow(["teclado", 2])
escritor.writerow(["ratón", 3])

with ZipFile("inventario.zip", "w", compression=ZIP_DEFLATED) as archivo_zip:
    archivo_zip.writestr("inventario.csv", buffer.getvalue())

Para archivos grandes, generar todo en memoria puede ser costoso. En esos casos, crea un archivo temporal controlado.

Niveles de compresión

with ZipFile(
    "imagenes.zip",
    "w",
    compression=ZIP_DEFLATED,
    compresslevel=6,
) as archivo_zip:
    ...

Un nivel más alto puede reducir el tamaño, pero requiere más CPU. Fotografías JPEG, vídeos y otros formatos ya comprimidos suelen reducirse poco.

Otros métodos de compresión

zipfile admite métodos según la versión de Python y módulos disponibles, como BZIP2 o LZMA. Para máxima compatibilidad con sistemas comunes, Deflate suele ser la opción más segura.

Guardar directorios vacíos

El recorrido de archivos no añade automáticamente carpetas vacías. Puedes crear una entrada terminada en barra:

archivo_zip.writestr("carpeta-vacia/", "")

Normalmente no es necesario, pero puede ser importante para plantillas de proyecto.

Verificar el contenido creado

from zipfile import ZipFile

with ZipFile("entrega.zip", "r") as archivo_zip:
    print(archivo_zip.namelist())
    archivo_danado = archivo_zip.testzip()

    if archivo_danado is not None:
        print(f"Entrada dañada: {archivo_danado}")

testzip() lee los archivos y comprueba sus CRC. Un resultado None indica que no detectó entradas corruptas.

Calcular hashes

Para verificar que el ZIP no cambió durante una transferencia, calcula SHA-256:

import hashlib
from pathlib import Path


def sha256(ruta):
    resumen = hashlib.sha256()
    with Path(ruta).open("rb") as archivo:
        for bloque in iter(lambda: archivo.read(1024 * 1024), b""):
            resumen.update(bloque)
    return resumen.hexdigest()

Publica el hash por un canal confiable cuando la integridad sea importante.

Crear el ZIP de forma segura

No escribas directamente sobre un archivo final importante. Crea un temporal y reemplaza el destino después de verificarlo:

temporal = destino.with_suffix(".zip.tmp")

# Crear y verificar temporal...
temporal.replace(destino)

Si el proceso falla, el ZIP anterior permanece intacto.

Función reutilizable

from pathlib import Path
from zipfile import ZipFile, ZIP_DEFLATED


def comprimir_carpeta(origen, destino):
    origen = Path(origen).resolve()
    destino = Path(destino).resolve()

    if not origen.is_dir():
        raise NotADirectoryError(origen)

    destino.parent.mkdir(parents=True, exist_ok=True)

    with ZipFile(destino, "w", compression=ZIP_DEFLATED) as archivo_zip:
        for ruta in origen.rglob("*"):
            if ruta.is_file() and ruta.resolve() != destino:
                archivo_zip.write(ruta, arcname=ruta.relative_to(origen))

    with ZipFile(destino) as archivo_zip:
        if archivo_zip.testzip() is not None:
            raise ValueError("El ZIP creado contiene una entrada dañada")

Copias de seguridad

Un ZIP no es por sí solo una estrategia completa de backup. Mantén varias versiones, almacena copias en otro dispositivo o ubicación y prueba restauraciones. No incluyas bases de datos activas sin realizar antes un volcado consistente.

Protección con contraseña

La biblioteca estándar puede leer ciertos ZIP cifrados, pero no ofrece una solución moderna y completa para crear archivos protegidos con cifrado fuerte. Para datos sensibles, utiliza una herramienta especializada y verifica el algoritmo. No confundas compresión con seguridad.

Errores frecuentes

Los fallos comunes son incluir rutas absolutas, comprimir el archivo de destino dentro de sí mismo, sobrescribir sin confirmación, almacenar secretos, asumir que todos los formatos se comprimen mucho y no verificar el resultado. También es frecuente confundir la función incorporada zip() con el módulo zipfile.

Conclusión

zipfile permite crear archivos ZIP portables con archivos, carpetas y contenido generado. Controla siempre arcname, excluye datos innecesarios, verifica con testzip() y escribe primero en un destino temporal cuando el proceso sea crítico. Para copias de seguridad reales, combina compresión con versionado, almacenamiento separado y pruebas de restauración.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Como evitar KeyError usando defaultdict em Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    defaultdict en Python: evita KeyError y simplifica diccionarios

    Aprende defaultdict en Python para evitar KeyError, contar, agrupar, crear estructuras anidadas y compararlo con get, setdefault y Counter.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Redimensionamento de imagens com Pillow em Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    Cómo redimensionar imágenes con Pillow en Python

    Redimensiona imágenes con Pillow en Python conservando proporciones, creando miniaturas, corrigiendo EXIF, procesando carpetas y exportando WebP.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Copiando e movendo arquivos com Python usando shutil
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    Cómo copiar y mover archivos en Python con shutil

    Aprende shutil en Python para copiar, mover, eliminar y comprimir archivos y carpetas con validaciones, hashes, logs y modo simulación.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Monitoramento de pastas em tempo real com Python Watchdog
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    Watchdog en Python: monitoriza carpetas en tiempo real

    Aprende Watchdog en Python para monitorizar carpetas, filtrar eventos, evitar duplicados, esperar archivos completos y automatizar procesos seguros.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Instalação offline de pacotes Python sem internet
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    Cómo instalar paquetes de Python sin conexión a Internet

    Aprende a instalar paquetes de Python sin Internet con pip download, ruedas, requirements.txt, --no-index, hashes y repositorios internos.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026
    Como acelerar código Python usando lru cache
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    lru_cache en Python: acelera funciones con caché

    Aprende lru_cache en Python: memoización, maxsize, cache_info, cache_clear, argumentos hashables, recursión y errores frecuentes.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026