From 456eb3a8819f31dd916ac5aeb867fe36f5c8790f Mon Sep 17 00:00:00 2001 From: "alexei.dolgolyov" Date: Sat, 18 Apr 2026 19:29:39 +0300 Subject: [PATCH] fix(windows): fix numpy DLL loading in embedded Python distribution - Generate numpy/_distributor_init_local.py during build so libopenblas can be located when running from the Windows installer - Add os.add_dll_directory() call at runtime as a fallback for embedded Python --- build-dist-windows.sh | 16 ++++++++++++++++ media_server/services/audio_analyzer.py | 15 +++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/build-dist-windows.sh b/build-dist-windows.sh index fa49ed3..de3a414 100644 --- a/build-dist-windows.sh +++ b/build-dist-windows.sh @@ -119,6 +119,22 @@ for whl in "$WHEEL_DIR"/*.whl; do unzip -qo "$whl" -d "$SITE_PACKAGES" done +# numpy wheels from PyPI don't include _distributor_init_local.py unless +# patched by delvewheel. In embedded Python, os.add_dll_directory() is never +# called, so libopenblas can't be found and numpy fails to import. +# Generate the missing loader here instead. +if [ -d "${SITE_PACKAGES}/numpy" ]; then + cat > "${SITE_PACKAGES}/numpy/_distributor_init_local.py" << 'EOF' +import os +import sys +if sys.platform == 'win32': + _libs = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'numpy.libs')) + if os.path.isdir(_libs): + os.add_dll_directory(_libs) +EOF + echo "Generated numpy/_distributor_init_local.py" +fi + cleanup_site_packages "$SITE_PACKAGES" "pyd" "dll" verify_frontend copy_app_files "$DIST_DIR" diff --git a/media_server/services/audio_analyzer.py b/media_server/services/audio_analyzer.py index 285dd98..3b6afbf 100644 --- a/media_server/services/audio_analyzer.py +++ b/media_server/services/audio_analyzer.py @@ -15,6 +15,21 @@ def _load_numpy(): global _np if _np is None: try: + import os + import sys + if sys.platform == 'win32': + # Embedded Python doesn't auto-load DLLs from numpy.libs; + # add the directory explicitly so libopenblas can be found. + try: + import importlib.util + spec = importlib.util.find_spec('numpy') + if spec and spec.submodule_search_locations: + numpy_dir = list(spec.submodule_search_locations)[0] + libs_dir = os.path.join(os.path.dirname(numpy_dir), 'numpy.libs') + if os.path.isdir(libs_dir): + os.add_dll_directory(libs_dir) + except Exception: + pass import numpy as np _np = np except Exception as e: