Li::Feel

りとるす的雑記帳。

Python3.4 + matplotlib + numpy + PyQt5のセットでPyInstallerを使ってexeファイルを作る

Pythonで作ったmatplotlib + numpy + PyQt5なGUIアプリをPyInstallerでexe化しようと思ったら3時間溶かしたのでメモ。

実行環境

  • Python3.4.5 32bit
    • Python3.5.x系だとうまくいかない。
  • Windows10 Pro 64bit
    • 64bitだけどPythonは32bitで。

numpyとscipyはこのサイトからダウンロード&インストール

http://www.lfd.uci.edu/~gohlke/pythonlibs/www.lfd.uci.edu

ファイルダイアログの読み込みの解決

PyQt5でファイルダイアログ等を使用する場合、tkinterのインポートも必要です。 PyInstallerはimportのあたりを解析してパッケージに含めるものを決めているようです。 インポートは結局こんな感じに。

from PyQt5.QtWidgets import (QMainWindow, QApplication, QWidget,
                             QGridLayout, QVBoxLayout, QHBoxLayout,QFileDialog,
                             QLabel, QLineEdit, QPushButton)

from window import Ui_Form
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5 import NavigationToolbar2QT as NavigationToolbar

from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import numpy as np
import random
import seaborn as sns
import copy

import tkinter
import tkinter.filedialog as FileDialog

hook-numpyを作成する

問題はこのままでは動きません。実行時に次のようなエラーが吐かれます。

Intel MKL FATAL ERROR: Cannot load mkl_intel_thread.dll.

そこで、StackOverflowの神々が書いたhook-numpy.pyというスクリプトをPyInstallerに追加します。 追加先は、C:\[Python34の位置]\Lib\site-packages\PyInstaller\hooksで、次のようなスクリプトを追加します。

from PyInstaller import log as logging 
from PyInstaller import compat
from os import listdir

mkldir = compat.base_prefix + "/Lib/site-packages/numpy/core" 
logger = logging.getLogger(__name__)
logger.info("MKL installed as part of numpy, importing that!")
binaries = [(mkldir + "/" + mkl, '') for mkl in listdir(mkldir) if mkl.startswith('mkl_')] 

stackoverflow.com

exe化のコマンド

ここまでやって、以下のようなコマンドで実行。

pyinstaller --hidden-import="tkinter" main.py

やっと動いた!寝る!