fix: pre-load tesseract51.dll by absolute path to fix transitive DLL deps
os.add_dll_directory alone is not enough on Windows. When Python loads the tesserocr .pyd via LOAD_LIBRARY_SEARCH_USER_DIRS, Windows finds tesseract51.dll in the added directory but then resolves tesseract's own transitive deps (leptonica, zlib, libpng etc.) using only the standard system search path -- not the user DLL dirs. Those libs live in Library\bin, not System32, so they're invisible and the load fails even though every DLL is present. Fix: call ctypes.WinDLL(absolute_path_to_tesseract51.dll) before the tesserocr import. LoadLibraryW with a full path anchors tesseract51.dll to Library\bin, so Windows searches that directory for its transitive deps. The already-loaded DLL is then returned from cache when the .pyd requests it, making the import succeed. Applied to ocr.py (test entry point), main.py, and shopper.py. Also updated install.bat smoke test and diagnostic to use the same fix. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -99,15 +99,15 @@ echo Installing tesserocr wheel...
|
||||
:: --- Smoke test: import key dependencies ---
|
||||
echo.
|
||||
echo Verifying dependencies...
|
||||
"%PYTHON%" -c "import os,sys;[os.add_dll_directory(p) for p in [os.path.join(sys.prefix,'Library',d) for d in ['bin','mingw-w64\\bin','usr\\bin']] if os.path.isdir(p)];import cv2,mss,numpy,tesserocr,discord,transitions,rapidfuzz" >nul 2>&1
|
||||
"%PYTHON%" -c "import os,sys,ctypes;lb=os.path.join(sys.prefix,'Library','bin');[os.add_dll_directory(os.path.join(sys.prefix,'Library',d)) for d in ['bin','mingw-w64\\bin','usr\\bin'] if os.path.isdir(os.path.join(sys.prefix,'Library',d))];ctypes.WinDLL(os.path.join(lb,'tesseract51.dll')) if os.path.isfile(os.path.join(lb,'tesseract51.dll')) else None;import cv2,mss,numpy,tesserocr,discord,transitions,rapidfuzz" >nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo.
|
||||
echo WARNING: Dependency check failed. Running diagnostics...
|
||||
echo.
|
||||
"%PYTHON%" -c "import os,sys; lb=os.path.join(sys.prefix,'Library','bin'); print(' Prefix:',sys.prefix); print(' Library/bin exists:',os.path.isdir(lb)); dlls=[f for f in (os.listdir(lb) if os.path.isdir(lb) else []) if any(k in f.lower() for k in ['tess','lepton'])]; print(' Tesseract DLLs found:',dlls if dlls else 'NONE - re-run install.bat'); [os.add_dll_directory(os.path.join(sys.prefix,'Library',d)) for d in ['bin','mingw-w64\\bin','usr\\bin'] if os.path.isdir(os.path.join(sys.prefix,'Library',d))]; __import__('tesserocr')" 2>&1
|
||||
"%PYTHON%" -c "import os,sys,ctypes; lb=os.path.join(sys.prefix,'Library','bin'); print(' Prefix:',sys.prefix); dlls=[f for f in (os.listdir(lb) if os.path.isdir(lb) else []) if any(k in f.lower() for k in ['tess','lepton'])]; print(' Tesseract DLLs in Library/bin:',dlls or 'NONE'); [os.add_dll_directory(os.path.join(sys.prefix,'Library',d)) for d in ['bin','mingw-w64\\bin','usr\\bin'] if os.path.isdir(os.path.join(sys.prefix,'Library',d))]; t=os.path.join(lb,'tesseract51.dll'); r=ctypes.WinDLL(t) if os.path.isfile(t) else None; print(' ctypes load tesseract51.dll:','OK' if r else 'skipped'); __import__('tesserocr'); print(' tesserocr import: OK')" 2>&1
|
||||
echo.
|
||||
echo If you see "NONE" above, re-run install.bat once more to let conda finish.
|
||||
echo If the error persists, see development.md for manual steps.
|
||||
echo *** Do NOT run "pip install tesserocr" manually - it builds from source and
|
||||
echo *** will always fail on Windows. Re-run install.bat to fix dependencies.
|
||||
) else (
|
||||
echo All key dependencies verified.
|
||||
)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import os
|
||||
import sys
|
||||
if os.name == 'nt':
|
||||
# Python 3.8+ requires explicit DLL directories; conda puts tesseract/leptonica in Library\bin
|
||||
import ctypes
|
||||
# Add all conda DLL dirs so Python's loader can find them
|
||||
for _dll_dir in [
|
||||
os.path.join(sys.prefix, 'Library', 'bin'),
|
||||
os.path.join(sys.prefix, 'Library', 'mingw-w64', 'bin'),
|
||||
@@ -9,6 +10,16 @@ if os.name == 'nt':
|
||||
]:
|
||||
if os.path.isdir(_dll_dir):
|
||||
os.add_dll_directory(_dll_dir)
|
||||
# Pre-load tesseract51.dll by absolute path so Windows anchors it to
|
||||
# Library\bin when resolving its own transitive deps (leptonica, zlib, etc.).
|
||||
# os.add_dll_directory alone is not enough: when Python loads the .pyd via
|
||||
# LOAD_LIBRARY_SEARCH_USER_DIRS, Windows finds tesseract51.dll there, but
|
||||
# then resolves tesseract's transitive deps using only System32 — not the
|
||||
# user DLL dirs. Loading by absolute path first puts tesseract in the cache
|
||||
# with Library\bin as its home, fixing the transitive search.
|
||||
_tess = os.path.join(sys.prefix, 'Library', 'bin', 'tesseract51.dll')
|
||||
if os.path.isfile(_tess):
|
||||
ctypes.WinDLL(_tess)
|
||||
from tesserocr import PyTessBaseAPI, OEM
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
# This must run BEFORE any import that might trigger tesserocr loading.
|
||||
import os, sys
|
||||
if sys.platform == "win32":
|
||||
import ctypes
|
||||
_conda_dll_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "conda_env", "Library", "bin")
|
||||
# Also check the conda env where this python lives (sys.prefix is reliable on Windows)
|
||||
for _dll_candidate in [
|
||||
_conda_dll_dir,
|
||||
os.path.join(sys.prefix, "Library", "bin"),
|
||||
@@ -13,6 +13,12 @@ if sys.platform == "win32":
|
||||
]:
|
||||
if os.path.isdir(_dll_candidate):
|
||||
os.add_dll_directory(_dll_candidate)
|
||||
# Pre-load tesseract51.dll by absolute path so Windows anchors its transitive
|
||||
# deps (leptonica, zlib, etc.) to Library\bin. os.add_dll_directory alone is
|
||||
# insufficient: transitive deps of a user-dir DLL are not searched there.
|
||||
_tess = os.path.join(sys.prefix, "Library", "bin", "tesseract51.dll")
|
||||
if os.path.isfile(_tess):
|
||||
ctypes.WinDLL(_tess)
|
||||
|
||||
from dataclasses import dataclass
|
||||
from input_layer import keyboard
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Fix: On Windows, Python 3.8+ requires os.add_dll_directory for conda-forge DLLs
|
||||
import os, sys
|
||||
if sys.platform == "win32":
|
||||
import ctypes
|
||||
for _dll_dir in [
|
||||
os.path.join(sys.prefix, "Library", "bin"),
|
||||
os.path.join(sys.prefix, "Library", "mingw-w64", "bin"),
|
||||
@@ -8,6 +9,9 @@ if sys.platform == "win32":
|
||||
]:
|
||||
if os.path.isdir(_dll_dir):
|
||||
os.add_dll_directory(_dll_dir)
|
||||
_tess = os.path.join(sys.prefix, "Library", "bin", "tesseract51.dll")
|
||||
if os.path.isfile(_tess):
|
||||
ctypes.WinDLL(_tess)
|
||||
|
||||
from beautifultable import BeautifulTable
|
||||
import logging
|
||||
|
||||
Reference in New Issue
Block a user