作成したスクリプトをpyinstallerを使用して実行ファイルにする際に幾つか詰まったところがあったので、記録として残します。
環境は以下のような感じです。
Python-3.7.4
pyinstaller-3.5
PyQt5-5.13.0
######pyqtgraphのimport順番
Exception: PyQtGraph requires one of PyQt4, PyQt5 or PySide; none of these packages could be imported.
[5708] Failed to execute script console
というエラーが出ていましたが、原因はimport文を書く順番でした。
スクリプトから実行する場合はある程度順番が逆でも問題ないのですが、pyinstallerで実行ファイルにした際には厳密に処理されるようです。
PyQt5を先にimportして、その後、PyQtGraphのimportをするようにしました。
######Qt5Core.dllなどを読み込まない
実行ファイルと同じディレクトリにQt5Core.dllなどを置いても読み込みませんでした。
環境変数でPATHを設定しておけば実行ファイルが起動できるようになることから、PATHが通っていないことがわかりました。
この為、以下のコードをPyQt5のimport文の前に挿入しました。
# Fix qt import error
# Include this file before import PyQt5
import os
import sys
import logging
def _append_run_path():
if getattr(sys, 'frozen', False):
pathlist = []
# If the application is run as a bundle, the pyInstaller bootloader
# extends the sys module by a flag frozen=True and sets the app
# path into variable _MEIPASS'.
pathlist.append(sys._MEIPASS)
# the application exe path
_main_app_path = os.path.dirname(sys.executable)
pathlist.append(_main_app_path)
# append to system path enviroment
os.environ["PATH"] += os.pathsep + os.pathsep.join(pathlist)
logging.error("current PATH: %s", os.environ['PATH'])
_append_run_path()
######specファイルなどで指定したファイルの読み込み
specファイルのdatasに指定したファイルは実行時にsys._MEIPASSで取得できるディレクトリに展開されるようです。
以下のように設定することで取得が出来ました。
if hasattr(sys, "_MEIPASS"):
FILE_PATH = os.path.join(sys._MEIPASS, 'test.png')
else:
FILE_PATH = os.path.join(os.path.dirname(__file__), 'test.png')