Ao analisar PDFs em lotes, por que cada processo deveria abrir o arquivo sozinho?
As tarefas de múltiplos processos devem passar parâmetros serializáveis e permitir que cada unidade de trabalho abra o documento de forma independente, em vez de compartilhar objetos Document ou Page. O seguinte testa cobertura segmentada e funções de trabalhador abertas de forma independente; para permanecer portátil e auditável, o exemplo é serializado e não é considerado um teste de desempenho de multiprocessos.
Ao processar PDFs em lotes, muitas pessoas desejam que vários processos compartilhem o mesmo objeto de documento, pensando que isso evitará problemas. Na verdade, os objetos Document e Page estão vinculados ao processo que os criou e podem surgir problemas ao usá-los em processos. Este artigo é adequado para desenvolvedores que precisam usar vários processos para dividir páginas PDF e extrair texto em lotes. Após a leitura, você saberá quais parâmetros devem ser passados para o processo filho, como o processo filho deve abrir o arquivo e em quais casos é necessário retornar a um único processo ou introduzir o OCR.
O exemplo usa amostras sintéticas e o código constrói a entrada na memória. Ele verifica o processamento de cobertura segmentada e arquivos abertos de forma independente e não representa garantia de todos os arquivos reais ou desempenho do produto. Antes de processar documentos importantes, guarde os originais e revise-os de acordo com os limites e itens de aceitação abaixo.
Ao analisar PDF em lotes, como cada processo deve abrir o arquivo? Conclusão de uma frase
As tarefas de vários processos devem passar parâmetros serializáveis e fazer com que cada unidade de trabalho abra o documento de forma independente, em vez de compartilhar objetos Document ou Page.
| sua situação | Práticas recomendadas | razão |
|---|---|---|
| Requer processamento em lote de vários processos de PDFs | Passe parâmetros serializáveis, como nome de arquivo, intervalo de números de páginas, etc., e cada processo filho chama pymupdf.open() sozinho | Document contém o ponteiro da estrutura C subjacente e o identificador de arquivo e não pode ser transmitido com segurança entre processos |
Deseja passar diretamente objetos Document ou Page | Não recomendado | Irá interromper devido a falha de pickle ou exceção devido a ponteiro inválido |
| Vários processos desejam gravar no mesmo arquivo de saída | Cada processo grava arquivos temporários independentes, que são mesclados pelo processo principal | Quando falta sincronização, o conteúdo pode ficar escalonado ou corrompido |
| A associação entre páginas é necessária, como mesclagem de tabelas entre páginas e indexação de texto completo | Volte ao processamento de processo único ou projete uma estratégia especializada de agregação em partes | Os processos são isolados uns dos outros e não podem compartilhar contexto |
Por que o objeto Document não pode ser passado para o processo filho?
A causa raiz é que Document contém internamente ponteiros e identificadores de arquivo para estruturas C subjacentes. Esses recursos estão vinculados ao espaço de memória do processo que os criou. Depois de serem passados entre processos, os ponteiros tornam-se inválidos e os identificadores não podem ser acessados legalmente por outro processo.
A abordagem correta é passar apenas os parâmetros serializáveis, como o nome do arquivo (string) e o intervalo de páginas, e permitir que cada processo filho chame pymupdf.open() independentemente em seu próprio espaço de memória. Este não é um compromisso de desempenho. O processo filho é uma entidade independente por direito próprio e requer sua própria instância de documento para executar operações de busca ou renderização com segurança.
Exemplo de composição independente
Veja a lista de importação do código abaixo para dependências. O código constrói a entrada na memória, facilitando a reprodução em um ambiente isolado.
import pymupdf
def partition(total, chunk):
if type(chunk) is not int or chunk <= 0:
raise ValueError("positive chunk required")
return [(start, min(start + chunk, total)) for start in range(0, total, chunk)]
def worker(raw, start, end):
with pymupdf.open(stream=raw, filetype="pdf") as doc:
return [(i, doc[i].get_text()) for i in range(start, end)]
with pymupdf.open() as doc:
for index in range(5):
doc.new_page().insert_text((50, 50), f"Page {index}")
raw = doc.tobytes()
tasks = partition(5, 2)
assert tasks == [(0, 2), (2, 4), (4, 5)]
results = [item for start, end in tasks for item in worker(raw, start, end)]
assert [i for i, text in results] == list(range(5))
assert all(f"Page {i}" in text for i, text in results)
assert partition(0, 2) == []
Dependências e instruções de operação
No exemplo, chunksize de pool.map usa o valor padrão 1, que é adequado para cenários em que a granularidade de uma única tarefa é grande. Se houver muitas páginas e o processamento de uma única página for rápido, chunksize poderá ser aumentado para reduzir a sobrecarga de comunicação entre processos. No entanto, este exemplo concentra-se na segurança e não no ajuste de desempenho.
Exemplo de síntese: entrada correta e limite de perigo
Entrada correta: Passe a tupla (segment_id, filename, start_page, end_page). onde filename é um caminho de string e start_page e end_page são números inteiros. Depois de receber os parâmetros, o processo filho abre o arquivo sozinho, processa o intervalo de números de página especificado e retorna a lista de resultados.
Limite de perigo:
- Número de página fora dos limites: se o intervalo de numeração de páginas for
(18, 25), mas o documento na verdade tiver apenas 20 páginas, um índice fora dos limites será acionado quando o processo filho acessar a página 21. - Passando
Documentdiretamente: será interrompido se o pickle falhar. - Vários processos gravando o mesmo arquivo: sem mecanismo de sincronização, o conteúdo de saída será intercalado ou danificado.
A solução é verificar imediatamente se o intervalo de números de página excede doc.page_count na entrada do processo filho e permitir que todas as operações de E/S usem caminhos de destino independentes ou buffers de memória. Objetos não serializáveis devem ser excluídos dos parâmetros da tarefa no estágio de design, em vez de depender da captura de exceções em tempo de execução.
📊 Comparação principal
| Dimensões | Passar objeto Documento | Passe parâmetros serializáveis (recomendado) |
|---|---|---|
| Ele pode ser transmitido entre processos? | Não, irá falhar devido ao picles | Sim, strings e inteiros podem ser passados diretamente |
| Propriedade dos recursos subjacentes | vinculado ao processo que o criou | Cada processo filho abre o arquivo sozinho |
| Comportamento de erro | pickle.PicklingError ou processo filho trava silenciosamente | Números de página que excedam limites podem ser verificados na entrada |
Critérios de Aceitação e Limites de Revisão Manual
| Observe o fenômeno | Possíveis razões | Decisão de tratar do assunto |
|---|---|---|
pickle.PicklingError ou travamento silencioso do processo filho | Passar objetos não serializáveis, como Documento/Página | Apenas tipos básicos como cadeias, inteiros e tuplas são passados |
| Alguns números de página retornam strings vazias | Os números das páginas excedem o número real de páginas, ou as páginas são imagens puras sem camadas de texto | Verifique os limites dos números das páginas; Marcação pura de página de imagem requer OCR, que é um comportamento esperado |
| O conteúdo do arquivo de saída está incorreto | Múltiplos processos gravam no mesmo arquivo | Cada processo escreve um arquivo temporário independente, e o processo principal se funde |
| O uso de memória aumenta linearmente com o número de processos | Cada processo carrega toda a documentação | Aceite essa despesa; Se o documento for muito grande, passe para o streaming de páginas |
Esse modo não é adequado para tarefas que exigem associação contextual entre páginas, como fusão de tabela entre páginas cruzadas ou construção de índice em texto completo, porque os processos são isolados uns dos outros. Ao atender a essas necessidades, você deve recorrer ao processamento de processo único ou projetar uma estratégia dedicada de agregação de blocos.
Além disso, o exemplo apenas verifica a "extração paralela segura" e não garante efeitos de ponta a ponta. Qualidade do texto, precisão da codificação e retenção de formatação ainda exigem revisão manual de amostragem. Atenção especial deve ser dada aos PDFs escaneados, pois a extração de texto simples pode falhar completamente, caso em que o OCR deve ser introduzido.
Se você ......
Se você precisar extrair texto PDF em paralelo
As tarefas são divididas pelo intervalo de número de página, passando apenas tipos básicos como nomes de arquivos e números de página, e cada processo filho abre arquivos de forma independente.
Se sua tarefa exigir mesclar resultados entre as páginas
Priorizar o retorno de processos individuais ou projetar estratégias de agregação de blocos; não force paralelismo.
Se você está lidando com PDFs digitalizados
Primeiro, confirme se existe uma camada de texto. Caso contrário, uma etapa de OCR deve ser adicionada ao processo antes de realizar a inspeção.
❓ Perguntas Frequentes (FAQ)
1. Por que o objeto Document não pode ser passado diretamente para o processo filho?
Document armazena internamente ponteiros e handles de arquivo apontando para a estrutura C subjacente. Esses recursos estão vinculados ao processo que os criou. A passagem entre processos torna-se inválida e interrompida se o pickle falhar.
2. Por que processos filhos abrem seus próprios arquivos?
Como entidades independentes, processos filhos precisam de suas próprias instâncias de documento para realizar extração ou renderização com segurança. Essa é a abordagem correta, não uma falha de desempenho.
3. O que fazer se o número da página exceder o intervalo especificado?
Na entrada do subprocesso, verifique imediatamente se o número da página excede doc.page_count; não continue acessando-o se ultrapassar o limite.
4. Vários processos podem gravar o mesmo arquivo de saída ao mesmo tempo?
Não recomendado. Sem mecanismos de sincronização, o conteúdo pode ser intercalado ou corrompido. Cada processo deve escrever um arquivo temporário independente e então fundi-lo pelo processo principal.
📝 Resumo
Ao multiprocessar PDFs, passar parâmetros serializáveis e permitir que cada subprocesso abra arquivos de forma independente é uma abordagem mais segura. Tarefas de associação entre páginas e arquivos escaneados precisam ser avaliados separadamente, e a verificação manual final ainda é realizada usando amostras reais.
Experimente agora: Envie seu documento para começar a traduzir, preservando a formatação original
Use checklists para tradução de documentos
Primeiro, verifique cuidadosamente a ordem da página, a localização da fonte e a integridade do texto, e então envie o mesmo exemplo de dessensibilização ao processo de tradução. Após a tradução, ainda é necessário verificar se o título, o texto principal e as legendas correspondem corretamente; não basta julgar apenas pela fluência do texto.
O OmniDoc (Entrada de Produto) oferece um portal de tradução de documentos em múltiplos formatos, e seu site oficial introduz OCR, glossários e recursos de tradução bilíngue. Para equipes que querem começar diretamente pelos arquivos, esse é um caminho que vale a pena avaliar com amostras reais. Por favor, use o arquivo anonimizado que você autorizou para enviar e verifique os resultados com a lista de verificação neste artigo. Isso não afirma que o OmniDoc utiliza as bibliotecas de código aberto ou algoritmos internos mencionados aqui, nem os exemplos substituem testes de desempenho do produto.
Base de interface de referência: Documento PyMuPDF


