PyInstallerでexe化したときにscipyでDLL load failed while importing _uarrayで落ちるのを解決した顛末の巻

PyInstallerでexe化したときにscipyでDLL load failed while importing _uarrayで落ちるのを解決した顛末の巻

はじめに

情報が少なかったので右往左往しまくりました。

exe化はできたのですが、scipyのimportのところでコケて落ちる。

File "scipy\_lib\_uarray\_backend.py", line 5, in <module>
ImportError: DLL load failed while importing _uarray: ダイナミック リンク ライブラリ (DLL) 初期化ルーチンの実行に失敗しました。

で、結局はPyInstallerのオプションで、

--collect-all "scipy"

としたらで解決できましたよ、と。

*ごめんなさいタイポがありました。。。「”scipy2」になってました。正しくは「”scipy”」です。。。修正しました(2022年6月16日)。

顛末

Pythonで作ったプログラムをPyInstallerでexe化して起動するところまで辿り着いたのですが、

scipy(ver. 1.8.0)のimportが絡む動作をしたときに、

ModuleNotFoundError: No module named 'scipy._lib._uarray._backend'

が出て落ちてしまいました。

なので問題解決につながりそうな、

https://stackoverflow.com/questions/51267453/scipy-import-error-with-pyinstaller


https://stackoverflow.com/questions/49559770/how-do-you-resolve-hidden-imports-not-found-warnings-in-pyinstaller-for-scipy?rq=1

を参考に

PyInstallerがインストールされているディレクトリ配下のにある

\PyInstaller\hooks\

hook-scipy.py

にいくつかの追加の記載を試した(”#####追加” の部分)ところ、

import glob
import os

from PyInstaller.compat import is_win
from PyInstaller.utils.hooks import get_module_file_attribute 
from PyInstaller.utils.hooks import collect_submodules    ##### 追加
from PyInstaller.utils.hooks import collect_data_files    ##### 追加

binaries = []
datas = collect_data_files('scipy')   ##### 追加

# Package the DLL bundle that official scipy wheels for Windows ship The DLL bundle will either be in extra-dll on
# windows proper and in .libs if installed on a virtualenv created from MinGW (Git-Bash for example)
if is_win:
    extra_dll_locations = ['extra-dll', '.libs']
    for location in extra_dll_locations:
        dll_glob = os.path.join(os.path.dirname(get_module_file_attribute('scipy')), location, "*.dll")
        if glob.glob(dll_glob):
            binaries.append((dll_glob, "."))

# collect library-wide utility extension modules
hiddenimports = ['scipy._lib.%s' % m for m in ['messagestream', "_ccallback_c", "_fpumode"]]
hiddenimports += collect_submodules('scipy')  ##### 追加

さっきのエラーは出なくなったのですが、

今度は

File "scipy\_lib\_uarray\_backend.py", line 5, in <module>
ImportError: DLL load failed while importing _uarray: ダイナミック リンク ライブラリ (DLL) 初期化ルーチンの実行に失敗しました。

と言われる様になってしまいました。

イベントビューアーからエラーログを見ると、

例外コード: 0xc0000005

というわけでsegmentation fault(メモリアクセス違反)が出ているのでした。

うーんなんでか全然わからん。

で、その後はPyInstallerの.specファイルのhidden importのところをいじってみたのですがうまくいかず、

他にもscipyのソースをいじってみたり、mkl入りのnumpyを入れてみたり、numpyやscipyのバージョン変えたり、「これかも」ということをいろいろ試しましたが、どれも解決には至りませんでした。うう、知識が足らぬ。

で、結局は

https://stackoverflow.com/questions/69651559/dll-load-failed-while-importing-defs

に記載のあった、

--collect-all "scipy"

を追加することでうまくいったのでした。scipyのバージョンは1.8.0です。

PyInstalleの実行コマンド例としては次の様になります。

python -m PyInstaller --onefile --collect-all "scipy" XXXXX.py

注1;実際はもっと色々オプションを追加しているのですが、簡単のため省略しています。

注2;XXXXXはpyファイル名です。

注3;hook-scipy.pyは変更したままなので、–collect-all “scipy”の追加だけで解決するのかは未確認です。

いやーありがとうございます。

具体的に何がどううまくいっていなかったのか、なぜうまくいったのかが未だに掴めていませんが、まあとりあえず、めでたしめでたし。

実施環境

*pyenvを使って、pipenvでの仮想環境下で実施しています。

MacBook 2017 (Intel Core m3, 1.2 GHz, RAM 8GB)(Boot CampでWindows10を導入)

Windows10 Home 21H2

PowerShell version; 5.1.19041.1682

Python 3.9.12

pyenv; 2.64.11

pipenv; version 2022.4.21

PyInstaller; 5.1

scipy; 1.8.0

numpy; 1.22.4

参考にした主なサイト

https://stackoverflow.com/questions/51267453/scipy-import-error-with-pyinstaller

https://stackoverflow.com/questions/69651559/dll-load-failed-while-importing-defs

https://stackoverflow.com/questions/49559770/how-do-you-resolve-hidden-imports-not-found-warnings-in-pyinstaller-for-scipy?rq=1