fix: replace custom tesserocr wheel with conda-forge package
The custom tesserocr-2.5.2 wheel was compiled on a specific machine against DLL versions that do not match a fresh conda-forge installation. This caused persistent ImportError: DLL load failed regardless of PATH or LoadLibraryExW approach. conda-forge's tesserocr package is compiled against the exact same conda-forge tesseract/leptonica binaries, so all DLL dependencies are automatically satisfied within the conda environment — no manual DLL path manipulation needed. Changes: - environment.yml: add tesserocr + tesseract as conda-forge packages, remove leptonica pin (no longer needed), remove custom wheel from pip - install.bat: replace wheel force-reinstall with pip uninstall cleanup - src/*.py: simplify DLL fix to os.add_dll_directory only Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
e1c18faf26
commit
d6c8d8d5f7
+4
-4
@@ -5,8 +5,9 @@ dependencies:
|
||||
- python=3.10
|
||||
- pywin32
|
||||
- pip
|
||||
- leptonica=1.78.0 # pinned: tesserocr wheel links against leptonica-1.78.0.dll
|
||||
- tesseract=5.1.0
|
||||
- tesserocr # conda-forge build — compiled against conda-forge tesseract/leptonica,
|
||||
# so all DLL deps are resolved automatically within the env
|
||||
- tesseract # version chosen by conda to match tesserocr
|
||||
- pkg-config
|
||||
- rapidfuzz=2.15.1
|
||||
- pip:
|
||||
@@ -31,7 +32,6 @@ dependencies:
|
||||
- pillow
|
||||
- discord.py
|
||||
- parse
|
||||
- dependencies/tesserocr-2.5.2-cp310-cp310-win_amd64.whl
|
||||
- typing_extensions
|
||||
- colorama
|
||||
- dataclasses-json
|
||||
- dataclasses-json
|
||||
|
||||
+3
-3
@@ -91,10 +91,10 @@ exit /b 1
|
||||
:env_created
|
||||
echo Botty Python: %PYTHON%
|
||||
|
||||
:: --- Force-reinstall the tesserocr wheel so the correct binary is always used ---
|
||||
:: --- Remove old pip-installed tesserocr wheel if present (replaced by conda-forge package) ---
|
||||
echo.
|
||||
echo Installing tesserocr wheel...
|
||||
"%PYTHON%" -m pip install --force-reinstall "%~dp0dependencies\tesserocr-2.5.2-cp310-cp310-win_amd64.whl" >nul 2>&1
|
||||
echo Removing old pip-installed tesserocr if present...
|
||||
"%PYTHON%" -m pip uninstall tesserocr -y >nul 2>&1
|
||||
|
||||
:: --- Smoke test via conda run (activates the full env like "conda activate botty") ---
|
||||
:: This is the only reliable way to ensure all DLL transitive deps are resolved.
|
||||
|
||||
+6
-18
@@ -1,27 +1,15 @@
|
||||
import os
|
||||
import sys
|
||||
if os.name == 'nt':
|
||||
import ctypes
|
||||
_dll_dirs = [d for d in [
|
||||
# Register conda DLL dirs so Python's .pyd loader (LOAD_LIBRARY_SEARCH_USER_DIRS)
|
||||
# can find tesserocr's dependencies (tesseract, leptonica, etc.)
|
||||
for _d in [
|
||||
os.path.join(sys.prefix, 'Library', 'bin'),
|
||||
os.path.join(sys.prefix, 'Library', 'mingw-w64', 'bin'),
|
||||
os.path.join(sys.prefix, 'Library', 'usr', 'bin'),
|
||||
] if os.path.isdir(d)]
|
||||
# Register dirs for Python's .pyd loader
|
||||
for _d in _dll_dirs:
|
||||
os.add_dll_directory(_d)
|
||||
# Preload tesseract51.dll via LoadLibraryExW with LOAD_LIBRARY_SEARCH_DEFAULT_DIRS.
|
||||
# Unlike ctypes.WinDLL/LoadLibraryW, this flag propagates to the ENTIRE
|
||||
# transitive dep chain (leptonica, mingw runtimes, etc.), resolving them
|
||||
# all via the user DLL dirs registered above.
|
||||
_LoadLibEx = ctypes.windll.kernel32.LoadLibraryExW
|
||||
_LoadLibEx.restype = ctypes.c_void_p
|
||||
_LoadLibEx.argtypes = [ctypes.c_wchar_p, ctypes.c_void_p, ctypes.c_ulong]
|
||||
for _d in _dll_dirs:
|
||||
_tess = os.path.join(_d, 'tesseract51.dll')
|
||||
if os.path.isfile(_tess):
|
||||
_LoadLibEx(_tess, None, 0x1000) # LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
|
||||
break
|
||||
]:
|
||||
if os.path.isdir(_d):
|
||||
os.add_dll_directory(_d)
|
||||
from tesserocr import PyTessBaseAPI, OEM
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
+6
-18
@@ -1,26 +1,14 @@
|
||||
# Fix: On Windows, Python 3.8+ requires os.add_dll_directory for conda-forge DLLs
|
||||
# that tesserocr depends on (tesseract51.dll, leptonica-1.78.0.dll).
|
||||
# This must run BEFORE any import that might trigger tesserocr loading.
|
||||
# Fix: On Windows, Python 3.8+ requires os.add_dll_directory for conda-forge DLLs.
|
||||
# Must run BEFORE any import that might trigger tesserocr loading.
|
||||
import os, sys
|
||||
if sys.platform == "win32":
|
||||
import ctypes
|
||||
_dll_dirs = [d for d in [
|
||||
for _d in [
|
||||
os.path.join(sys.prefix, "Library", "bin"),
|
||||
os.path.join(sys.prefix, "Library", "mingw-w64", "bin"),
|
||||
os.path.join(sys.prefix, "Library", "usr", "bin"),
|
||||
] if os.path.isdir(d)]
|
||||
for _d in _dll_dirs:
|
||||
os.add_dll_directory(_d)
|
||||
# Preload tesseract51.dll via LoadLibraryExW with LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
|
||||
# (0x1000) so transitive deps are resolved via user DLL dirs, not just PATH.
|
||||
_LoadLibEx = ctypes.windll.kernel32.LoadLibraryExW
|
||||
_LoadLibEx.restype = ctypes.c_void_p
|
||||
_LoadLibEx.argtypes = [ctypes.c_wchar_p, ctypes.c_void_p, ctypes.c_ulong]
|
||||
for _d in _dll_dirs:
|
||||
_tess = os.path.join(_d, "tesseract51.dll")
|
||||
if os.path.isfile(_tess):
|
||||
_LoadLibEx(_tess, None, 0x1000)
|
||||
break
|
||||
]:
|
||||
if os.path.isdir(_d):
|
||||
os.add_dll_directory(_d)
|
||||
|
||||
from dataclasses import dataclass
|
||||
from input_layer import keyboard
|
||||
|
||||
+5
-15
@@ -1,23 +1,13 @@
|
||||
# Fix: On Windows, Python 3.8+ requires os.add_dll_directory for conda-forge DLLs
|
||||
# that tesserocr depends on (tesseract51.dll, leptonica-1.78.0.dll).
|
||||
# Fix: On Windows, Python 3.8+ requires os.add_dll_directory for conda-forge DLLs.
|
||||
import os, sys
|
||||
if sys.platform == "win32":
|
||||
import ctypes
|
||||
_dll_dirs = [d for d in [
|
||||
for _d in [
|
||||
os.path.join(sys.prefix, "Library", "bin"),
|
||||
os.path.join(sys.prefix, "Library", "mingw-w64", "bin"),
|
||||
os.path.join(sys.prefix, "Library", "usr", "bin"),
|
||||
] if os.path.isdir(d)]
|
||||
for _d in _dll_dirs:
|
||||
os.add_dll_directory(_d)
|
||||
_LoadLibEx = ctypes.windll.kernel32.LoadLibraryExW
|
||||
_LoadLibEx.restype = ctypes.c_void_p
|
||||
_LoadLibEx.argtypes = [ctypes.c_wchar_p, ctypes.c_void_p, ctypes.c_ulong]
|
||||
for _d in _dll_dirs:
|
||||
_tess = os.path.join(_d, "tesseract51.dll")
|
||||
if os.path.isfile(_tess):
|
||||
_LoadLibEx(_tess, None, 0x1000)
|
||||
break
|
||||
]:
|
||||
if os.path.isdir(_d):
|
||||
os.add_dll_directory(_d)
|
||||
|
||||
from beautifultable import BeautifulTable
|
||||
import logging
|
||||
|
||||
Reference in New Issue
Block a user