概要
pyinstaller を用いて、sklearnを内部で使用するライブラリをバイナリ化したときのこと。
hook.py
にて
sklearn
を hidden import
しているのにもかかわらず、
実際にバイナリを実行する際、
No module name 'sklearn.ensemble._forest'
のようなエラーが出てしまっていた。
何が起きていたか
実際にバイナリが吐き出されたフォルダに行き、
sklearn
のフォルダに行くと、
root@b87a64080bd4:/myproject# cd sklearn/
root@b87a64080bd4:/myproject/sklearn# ls -l
total 1448
drwxr-xr-x 2 root root 4096 Feb 22 02:42 __check_build
-rwxr-xr-x 1 root root 1429088 Feb 19 10:41 _isotonic.cpython-36m-x86_64-linux-gnu.so
drwxr-xr-x 2 root root 4096 Feb 22 02:42 cluster
drwxr-xr-x 6 root root 4096 Feb 22 02:42 datasets
drwxr-xr-x 2 root root 4096 Feb 22 02:42 decomposition
drwxr-xr-x 3 root root 4096 Feb 22 02:42 ensemble
drwxr-xr-x 2 root root 4096 Feb 22 02:42 linear_model
drwxr-xr-x 2 root root 4096 Feb 22 02:42 manifold
drwxr-xr-x 3 root root 4096 Feb 22 02:42 metrics
drwxr-xr-x 2 root root 4096 Feb 22 02:42 neighbors
drwxr-xr-x 2 root root 4096 Feb 22 02:42 preprocessing
drwxr-xr-x 2 root root 4096 Feb 22 02:42 svm
drwxr-xr-x 2 root root 4096 Feb 22 02:42 tree
drwxr-xr-x 2 root root 4096 Feb 22 02:43 utils
のようになっていた。うまくバイナリ化が階層的に行われていたかと思ったが、
root@b87a64080bd4:/myproject/sklearn# cd ensemble/
root@b87a64080bd4:/myproject/sklearn/ensemble# ls -l
total 4
drwxr-xr-x 2 root root 4096 Feb 22 02:42 _hist_gradient_boosting
こうなっていた。
すなわち、 /myproject/sklearn/ensemble/_forest
のようなものは確かに存在していなかった。
解決策
hook.py
の hidden_import
に
sklearn.ensemle
などを使うものはきちんと追加する必要がある。
よくよく考えれば当たり前であるが、
https://github.com/scikit-learn/scikit-learn/tree/main/sklearn/ensemble
ここのソースディレクトリなどをみてもわかるように、
sklearn/ensemble に __init__.py
が存在していることからも、
きちんとその階層をhidden_import
に追加しておくのが必要である。
たぶんpyinstaller をよく理解せずに今まで使っていたのが原因だったが、
一回理解することで次からスムーズに運用できるかなと思った。
以上。