Python PDF Zip Files
Nota: Este script exige conhecimento avançado, level Full Stack. Se precisar de ajuda, não hesite, entre em contato.
Abaixo você encontra os procedimentos de configuração e o código-fonte em Python desenvolvido para agrupar e compactar arquivos PDF em volumes ZIP respeitando um limite máximo de tamanho por arquivo ZIP (padrão: 15 MB).
Procedimento Operacional Padrão (POP)
1. Criar o ambiente virtual (venv) no Windows
Ainda não criou o seu ambiente localhost? Veja no link abaixo como fazer.
2. Requisitos de Bibliotecas
Este script utiliza exclusivamente bibliotecas nativas da biblioteca padrão do Python (zipfile, importlib, pathlib, tempfile e typing). Portanto, não é necessária a instalação de pacotes externos via pip para sua execução.
3. Como configurar e executar o script
-
Estrutura de Rotas (routes.py): O script busca o módulo de rotas em
app/builder/routes.pya partir da raiz do projeto. Certifique-se de que a rota referente ao appPDFZipperesteja configurada com os caminhos válidos de entrada (input.path) e saída (output.path). -
Limite de Tamanho (SIZE_LIMIT_MB): Ajuste a variável
SIZE_LIMIT_MBno código (definida como15por padrão) para estipular o limite máximo que cada arquivo.zipgerado deve possuir. -
Padrão de Nome do Arquivo ZIP: Edite a variável
zip_filenamedentro da funçãozip_pdfs()para alterar o prefixo dos arquivos de saída gerados (ex:DOEM_..._001.zip). -
Lógica de Processamento: O script varre o diretório de entrada em busca de arquivos
.pdf, calcula dinamicamente o tamanho final compactado em memória/pasta temporária e agrupa o máximo de arquivos possível por volume ZIP sem ultrapassar o limite estabelecido.
Código-Fonte
# REQUEST LIB PYTHON
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ===========================
# IMPORTS
# ===========================
import zipfile
import importlib.util
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import List
# ===========================
# LOAD ROUTES
# ===========================
def load_routes_module() -> list:
root = Path(__file__).parents[3]
routes_path = root / "app" / "builder" / "routes.py"
if not routes_path.exists():
raise FileNotFoundError(f"routes.py não encontrado em {routes_path}")
spec = importlib.util.spec_from_file_location("routes", str(routes_path))
if spec is None or spec.loader is None:
raise ImportError("Falha ao criar ModuleSpec para routes.py")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module) # type: ignore
return getattr(module, "routes", [])
def get_io_paths(app_name: str) -> tuple:
routes = load_routes_module()
for r in routes:
if r.get("app", "") == app_name:
input_path = r["input"]["path"] or ""
output_path = r["output"]["path"] or ""
return Path(input_path), Path(output_path)
raise RuntimeError(f"Rota não encontrada para {app_name}")
# ===========================
# CONFIG
# ===========================
APP_NAME = "PDFZipper"
INPUT_DIR, OUTPUT_DIR = get_io_paths(APP_NAME)
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
SIZE_LIMIT_MB = 15 # <--- alterado de 19.5 para 15
SIZE_LIMIT_BYTES = int(SIZE_LIMIT_MB * 1024 * 1024)
# ===========================
# CORE FUNCTIONS
# ===========================
def get_pdf_files(path: Path) -> List[Path]:
return [f for f in path.glob("*.pdf") if f.is_file()]
def calculate_zip_size(file_list: List[Path]) -> int:
with TemporaryDirectory() as temp_dir:
temp_zip_path = Path(temp_dir) / "temp.zip"
with zipfile.ZipFile(temp_zip_path, "w", zipfile.ZIP_DEFLATED) as zipf:
for file in file_list:
zipf.write(file, arcname=file.name)
return temp_zip_path.stat().st_size
def zip_pdfs():
files = get_pdf_files(INPUT_DIR)
if not files:
print("Nenhum arquivo PDF encontrado.")
return
folder_counter = 1
while files:
group = []
for file in files:
test_group = group + [file]
zip_size = calculate_zip_size(test_group)
if zip_size <= SIZE_LIMIT_BYTES:
group.append(file)
else:
break # Atingiu o limite
if not group:
print(
f"Aviso: Arquivo {files[0].name} excede sozinho o limite de {SIZE_LIMIT_MB} MB compactado."
)
group = [files[0]]
# zip_filename = OUTPUT_DIR / f"Pasta{folder_counter:03}.zip"
# zip_filename = OUTPUT_DIR / f"DecretosIndividuais{folder_counter:03}.zip"
# zip_filename = OUTPUT_DIR / f"DecretosAdmissao{folder_counter:03}.zip"
# zip_filename = OUTPUT_DIR / f"DecretosDemissao{folder_counter:03}.zip"
zip_filename = OUTPUT_DIR / f"DOEM_02012009_12062025_{folder_counter:03}.zip"
with zipfile.ZipFile(zip_filename, "w", zipfile.ZIP_DEFLATED) as zipf:
for file in group:
zipf.write(file, arcname=file.name)
print(f"✅ {zip_filename.name} criado com {len(group)} arquivos.")
# Remove os processados da lista
files = [f for f in files if f not in group]
folder_counter += 1
print("✅ Processamento concluído.")
# ===========================
# MAIN
# ===========================
if __name__ == "__main__":
zip_pdfs()