サマリ
- Sklearn, matplotlib等を利用したPythonスクリプトを Pyinstallerでexeファイル化した際のはまったポイントと対処方法の備忘録。
環境
- MS Windows 10 Pro (32bit, 1709)
- Anaconda3-5.0.1-Windows-x86.exe (Python 3.6.3)
- pycharm-community-2017.3.2.exe
はまったポイント
- Python3.6対応
- Sklearn 対応
- Multiprocessing 対応
- Matplotlibを使ったグラフ描画 対応
詳細
Python3.6 対応
問題点
Python 3.6スクリプトをPyinstallerでコンパイルすると、下記メッセージがでて失敗する。
AttributeError: 'str' object has no attribute 'items'
対処方法
最新のPyinstaller 3.3.1 を導入。
pip install --upgrade pyinstaller
参照サイト
https://qiita.com/y-tsutsu/items/f687cf4b57442557aade
https://github.com/pyinstaller/pyinstaller/releases
Sklearn対応
問題点
Pyinstaller によるコンパイルは成功するものの、コンパイルしたexeファイルを実行すると、下記エラーメッセージが発生。
ModuleNotFoundError: No module named 'typedefs'
[7436] Failed to execute script myprog
対処方法
- コンパイル --> exeファイル実行時エラーメッセージで出てきたmodule を myprog.spec のhiddenimports に追加 --> 再コンパイル、を繰り返す。
- myprog.spec は 最初のコンパイル時に生成される。
※ より効率が良い方法もあるようだが、それではうまく行かなかった。
1回目 エラーメッセージ
File "sklearn\neighbors\dist_metrics.pyx", line 52, in init sklearn.neighbors.dist_metrics
ModuleNotFoundError: No module named 'typedefs'
[7436] Failed to execute script myprog
2回目 エラーメッセージ
File "sklearn\neighbors\quad_tree.pxd", line 54, in init sklearn.tree._tree
ModuleNotFoundError: No module named 'sklearn.neighbors.quad_tree'
[592] Failed to execute script myprog
3回目 エラーメッセージ
File "sklearn\tree\_utils.pxd", line 78, in init sklearn.neighbors.quad_tree
ModuleNotFoundError: No module named 'sklearn.tree._utils'
[2732] Failed to execute script myprog
参考サイト
https://stackoverflow.com/questions/15114695/pyinstaller-import-error
より効率の良いやり方?
https://stackoverflow.com/questions/35478526/pyinstaller-numpy-intel-mkl-fatal-error-cannot-load-mkl-intel-thread-dll
Multiprocessing対応
問題
Multiprocessing.pool関数を用いたスクリプトをコンパイルし、実行しても以下のエラーがでて失敗する。
Error: no such option: --multiprocessing-fork
対処方法
- UPX化 のDisable
- Myprog.py に
multiprocessing.freeze_support()
を追加(下記まとめmyprog.py
参照)。
※ 参考サイトでは onefileの場合は上記対処だけでは無理と記述があったが、手元ではできた。
参考サイト
Matplotlibを使ったグラフ描画
問題
Matplotlibを用いたグラフ描画スクリプトをコンパイルし、実行しても以下のエラーがでて失敗する。
This application failed to start because it could not find or load the Qt platform plugin "windows"
in "".
Reinstalling the application may fix this problem.
対処方法
- PyQt5のインストール
# pip install PyQt5
Collecting PyQt5
Using cached PyQt5-5.9.2-5.9.3-cp35.cp36.cp37-none-win32.whl
Collecting sip<4.20,>=4.19.4 (from PyQt5)
Using cached sip-4.19.6-cp36-none-win32.whl
Installing collected packages: sip, PyQt5
Successfully installed PyQt5-5.9.2 sip-4.19.6
まとめ
myprog.py (一部抜粋)
- Multiprocessing対応コードの追加
import multiprocessing
import sys
<メイン処理>
if __name__ == '__main__':
if sys.platform.startswith('win'):
# On Windows calling this function is necessary.
multiprocessing.freeze_support()
<メイン処理呼び出し>
myprog.spec
-
pyinstaller myprog.py
で生成されたmyprog.spec
を修正。 - Sklearn対応のため、実行時ModuleNotFoundErrorエラーがなくなるまで、hiddenimports にモジュールを追加。
- Multiprocessing対応のため、
upx=False
とする。
# -*- mode: python -*-
block_cipher = None
himports = [
'cython', 'sklearn', 'sklearn.neighbors.typedefs', 'sklearn.neighbors.quad_tree', 'sklearn.tree._utils']
a = Analysis(['myprog.py'],
pathex=['C:\\Users\\XXXXX\\PycharmProjects\\myprog'],
binaries=[],
datas=[],
hiddenimports=himports,
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
name='myprog',
debug=False,
strip=False,
upx=False,
runtime_tmpdir=None,
console=True)
コンパイル方法
pyinstaller myprog.spec