werry-chanの日記.料理とエンジニアリング

料理!コーディング!研究!日常!飯!うんち!睡眠!人間の全て!

PyInstallerでsklearnを.exe化する時の注意

自分が実験で使うpythonコードをpyinstallerで.exe化しようと思ったんですが,謎のエラーが大量発生してハマりました.

その時の解決策をメモしようと思ったので,ブログに残しておきます.


まず,temp.pyが以下のようだとしましょう.

import sklearn

if __name__ == "__main__":
    #####省略######

このようなコードをbash

pyinstaller temp.py --onefile

と実行した時にぶち当たるのは,

50909 WARNING: Hidden import "sklearn.utils.sparsetools._graph_validation" not found!
50909 WARNING: Hidden import "sklearn.utils.sparsetools._graph_tools" not found!
50910 WARNING: Hidden import "sklearn.utils.lgamma" not found!

といったようなものでしょう.

WARING内容を見れば予想できますが,cross valuationを使ったりするとこのようなエラーが吐かれます.

表示されたWARNIGの部分を参照して,.specを書き換えます.

例えばtemp.specを以下のように書き換えます.

#####省略######
a = Analysis(
             #####省略######
             hiddenimports=[
                          'sklearn.utils.sparsetools._graph_validation',
                          'sklearn.utils.sparsetools._graph_tools',
                          'sklearn.utils.lgamma'
                          ],
             #####省略######
             )
#####省略######

これでとりあえずWARNIGの該当部分が解消されると思います.

このサイトを参考にしました↓
https://qiita.com/jokitsu2/items/4020ee85056f3a21c11b




他にも以下のようなエラーが吐かれた場合がありました.

Reason: Incompatible library version: libopencv_imgcodecs.3.3.dylib requires version 48.0.0 or later, but libpng16.16.dylib provides version 45.0.0

このエラーが吐かれた場合には,また.specファイルを以下のように書き足しましょう.

#####省略######
a = Analysis(
             #####省略######
             )
a.binaries = a.binaries - TOC([('libpng16.16.dylib',None,None)])
#####省略######

これで問題が解消されるかと思います.




次にハマったポイントは,.exe化した後のファイルの実行時です.

.exeを実行した時に,sklearnのモジュールを実行部分で無限ループ(infinite loop)が発生しました.

これを解消するための方法は以下のサイトを参照して解決しました.
https://github.com/pyinstaller/pyinstaller/issues/4110

joblibのバージョンに相性的な問題があるようです.

pip install joblib==0.11

joblibを0.11にすることで僕は問題は解決しました.

しかしながら,参考にしたサイトにはscikit-learnのバージョンを合わせる必要があるとも書いてありました.

一応参考にしたサイトでは,以下のようにバージョンを合わせていました.

pip install joblib==0.11
pip install scikit-learn==0.21.1

これでsklearnを入れた.pyをpyinstallerで.exe化することができると思います.