fix: fenêtres fantômes PyInstaller — désactiver ProcessPoolExecutor en mode frozen

ProcessPoolExecutor relançait l'exe pour chaque sous-processus de
rastérisation sous PyInstaller --onefile, créant une fenêtre GUI par page.
En mode frozen, la rastérisation est maintenant séquentielle.

Aussi: remplacement du mutex Windows par un file lock (msvcrt.locking)
plus fiable pour la protection anti-multi-instance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-18 00:51:54 +01:00
parent 65a02952c5
commit d1bdfb1aca
2 changed files with 230 additions and 3 deletions

View File

@@ -3583,15 +3583,20 @@ def redact_pdf_raster(original_pdf: Path, audit: List[PiiHit], out_pdf: Path, dp
image_rects_by_page[pno] = img_rects
doc.close() # fermer AVANT le fork
n_workers = min(n_pages, os.cpu_count() or 4)
tasks = [
(str(original_pdf), pno, rects_as_tuples.get(pno, []), dpi, ogc_label, jpeg_quality,
image_rects_by_page.get(pno, []))
for pno in range(n_pages)
]
with ProcessPoolExecutor(max_workers=n_workers) as pool:
results = sorted(pool.map(_rasterize_page, tasks), key=lambda x: x[0])
# Mode frozen (PyInstaller --onefile) : ProcessPoolExecutor relance l'exe
# et ouvre des fenêtres GUI fantômes → séquentiel obligatoire
if getattr(sys, 'frozen', False) or n_pages <= 2:
results = sorted([_rasterize_page(t) for t in tasks], key=lambda x: x[0])
else:
n_workers = min(n_pages, os.cpu_count() or 4)
with ProcessPoolExecutor(max_workers=n_workers) as pool:
results = sorted(pool.map(_rasterize_page, tasks), key=lambda x: x[0])
# Assemblage final (séquentiel, rapide)
out = fitz.open()