Wilberhg's blog

Escrita Segura em Excel com Openpyxl em Ambientes Multithreading

Entendendo o Conceito

A biblioteca openpyxl é uma das ferramentas mais comuns para manipulação de arquivos Excel no formato .xlsx no ecossistema Python. No entanto, ela não fornece suporte nativo a operações simultâneas em ambientes multithreading, o que significa que seus objetos de planilha (Workbook) não são thread-safe para modificações paralelas. Se múltiplos fluxos de execução tentarem alterar células ou salvar o arquivo ao mesmo tempo, ocorrerão inconsistências graves, corrupção do documento ou falhas de runtime devido à alteração de estruturas internas durante a iteração.

Para superar essa limitação, torna-se indispensável o uso de primitivas de sincronização que controlem o acesso ao arquivo. O emprego de uma trava de exclusão mútua, conhecida como lock ou mutex, assegura que apenas uma thread realize a escrita ou execute o processo de gravação por vez. Essa abordagem protege as seções críticas do código, garantindo a integridade dos dados finais sem que ocorram colisões de concorrência.

Passo a Passo

O procedimento a seguir demonstra como estruturar uma classe que protege as operações do openpyxl por meio do módulo threading.

Primeiramente, instale a biblioteca de manipulação de planilhas por meio do gerenciador de pacotes pip:

pip install openpyxl

Em seguida, implemente a lógica de sincronização encapsulando o workbook e a trava correspondente:

import threading
import time
from openpyxl import Workbook

class ThreadSafeExcelWriter:
    def __init__(self, filename):
        self.filename = filename
        self.wb = Workbook()
        self.ws = self.wb.active
        self.lock = threading.Lock()

    def write_data(self, row, col, value):
        with self.lock:
            self.ws.cell(row=row, column=col, value=value)

    def save_workbook(self):
        with self.lock:
            self.wb.save(self.filename)

def worker_task(writer, start_row, value):
    for i in range(5):
        writer.write_data(row=start_row + i, col=1, value=value)
        time.sleep(0.01)

writer = ThreadSafeExcelWriter("dados_seguros.xlsx")

threads = []
for index in range(1, 6):
    t = threading.Thread(target=worker_task, args=(writer, index * 10, f"Thread-{index}"))
    threads.append(t)
    t.start()

for t in threads:
    t.join()

writer.save_workbook()

Explicando o código

A estrutura desenvolvida utiliza comandos específicos da linguagem para viabilizar o comportamento concorrente seguro:

Observações

Referências

  1. Documentação Oficial do Openpyxl: https://openpyxl.readthedocs.io/
  2. Discussão sobre Thread Safety no Openpyxl: https://stackoverflow.com/questions/11234203/openpyxl-thread-safe
  3. Registro de Falha de Concorrência do HeptaPod: https://foss.heptapod.net/openpyxl/openpyxl/-/issues/228
  4. Documentação de Threading e Locks do Python: https://docs.python.org/3/library/threading.html

#concurrency #excel #openpyxl #python #threading #threadsafe