pythonをexe化するpyinstallerについて

python By Output不足なエンジニア

通常は受託開発しているので開発言語の実行環境が本番にない事をはあり得ないのですが、スキャンずれの修正等は案件として開発しているわけではないので、python実行環境がない顧客に使ってもらう可能性は多々あります。Webサービス化するのが順当だと思いますが、正直どれだけ需要があり、OCR読み取り精度向上に貢献するかわからないのでまずはexeにして内部で検証してみるのが良いかと思っています。exe化するライブラリがあるのですが色々躓きポイントがあったので備忘を兼ねて記載します。
ちなみに、exe化は出来たのですが、強引な解決方法を取っているため商用ではやらないほうが良い項目もあります。特に商用ではライセンスが絡むところもありますので注意してください。(まだあくまで自宅でのお勉強なので。)



pyinstallerについて

pythonをexe化するライブラリです。pipで簡単に導入でき、簡単なプログラムであれば何の問題もなくexe化してくれます。pipでインストールしたら、
pyinstaller "exeにしたいスクリプト".py --onefile [--noconsole]
だけで簡単にexeになります。(noconsole はexeがコンソール出力しないようにするオプション)ただ、関数の呼び出し階層が深くなったり、バージョンの組み合わせによって色々手を入れる必要があるみたいです。
私の環境はWindows10, python=3.6, pyinstaller==3.4 です。

躓きポイント


Recursion error : maximum recursion depth exceeded

再帰しすぎとのこと。特に再帰してないと思ったのですが、OpenCVの関数で再帰しているかpyinstallerの関数が再帰しているのかもしれません。pyinstallerでexe化しようとすると、カレントに”exeにしたいスクリプト.spec”というファイルが作成されるので、このファイルを開いて処理の冒頭に下記を追加すると(一般には)うまくいくみたいです。

import sys
sys.setrecursionlimit(50000)

上記で再帰の上限を変更しても同様のエラーが出る場合、pyinstallerで指定するファイルをこの .spec ファイルにすると、うまくいきました。(次のエラーが出るようになった)
pyinstaller "exeにしたいスクリプト".spec --onefile


Cannot find existing PyQt5 plugin directories

PyQt5というGUIツール作成のフレームワークとのことです。商用利用にはライセンスの制限がある⁉ようなので、ひょっとしたらこの試みがおじゃんかも知れません。本エラーがでたらライセンスの確認をしましょう。
とりあえずこのブログに記載するソースはすべてプライベートで作っているものなので、お勉強としてpipでPyQt5をインストールして先に進みます。(商用で使う場合は要検討・検証だな…)


UnicodeDecodeError: ‘utf-8’ codec can’t decode ~

python2系ではよく見たエラーですね。新人の頃やっとjavaを覚えたのに数理計算をpythonでやってるシステムがあるからTalendで実現可能か検証してって言われた時を思い出します。
スタックトレースに\PyInstaller\compat.py line 370, in exec_command でエラーが出ていると書いてあるので、下記修正をします(危ない修正なので自己責任でお願いします)

 
# out = out.decode(encoding)
out = out.decode(encoding, errors='ignore')

unicodeのdecodeエラーを無視します(え…)。unicodeはコメントにしかないと思いますが、PyQt5はC++だしnumpy, pandasは内部でCを使っているので
文字化け→意図しないエスケープでコメント終了→コメントが命令として解釈される
が発生しないか心配です。
※C言語で表示の表の字が化けるとそこでエスケープが切れるので、「変数の中身を表示する」なんてコメント書いて残念な思いをすることがあります。
exe化せず他の方法を取れないか、exe化する時だけコメント全削除するなど何かしらの対策が必要かと思います。

ただ、かなりお手軽にexe化できるので、チーム内の便利ツール作ったとかそういう用途では非常に役立つと思います。商用で使う際はくれぐれもライセンスに注意してください。pipで普通に入ってしまうので。

【追記】不要ライブラリの除外でPyQt5インストール回避

condaで新規環境をcreateして本当に必要なライブラリのみに絞った環境を作成したところ、PyQt5のインストールは回避できました。python=3.7に切り替えて上手くいったのかと思ったのですが、3.6でも同様に不要なライブラリを除外すればexe化できたので、ライブラリの組み合わせに問題がある場合もあるようです。

Cannot find existing PyQt5 plugin directories

上記が発生した場合は、まっさらな新規環境に必要なライブラリのみ入れてexe化してみてください。


カテゴリー:python,エラー対処

Output不足なエンジニア

統計が好きになれず、機械学習やったら必然的に統計が必要になるだろうと思ったら想像以上に機械学習にハマる。数学は芸術なので商売にするつもりはないけど、DeepLearningは数学じゃないし商売にしたいと思っているところ。画像処理がメイン。