#もし私がフリーザ様なら
地球は消えていたでしょう。
表題の件はそれくらい、久しぶりにハマりました。
さて、Pythonでプログラムを記述して、使ってもらおうと思っても、
専門的な知識がない人に、コマンド画面を叩いて.pyファイルを実行させることはおろか、
Pythonとは、ANACONDAとは、インストール?パス?はて?
と、直接展開には高いハードルが立ちふさがります。
そこでPythonには記述したプログラムをExeファイル化してくれる方法がいくつか存在しており
その中でもポピュラーな【pyinstaller】というものがあります。
コマンド画面で、記述したファイルを指定して、実行するだけでExeファイルが出来ます。
ExeファイルであればPythonがインストールされていないPCでも
プログラムを実行することが出来ます。
実は今までの私はただ運がよかっただけで、何不自由なくExe化できていました。
しかし、ある日突然pyinstallerは牙を剥きました。
備忘録の意味も含め記述します。
※分かりにくい箇所はご指摘ください。
#目次
■原因はMatplotlib
■涙が出そうなRecursionError: maximum recursion depth exceeded
■それでも明日はUnicodeDecodeError: 'utf-8' codec can't decode byte 0x83 in position 130: invalid start byte
ちなみに、PyQt5がインストールされていないことがあるので、
pip install PyQt5
こちらのインストールも忘れないようにしましょう。
##■原因はMatplotlib
かいつまんでお話ししますので、かなりの部分を割愛していますが、
Matplotlibを使用しており、そのplot部分でExeプログラムは断りもなく強制終了していました。
黙って終了するのはクソです。
Webとかで【Python Exe エラー】とか【Python Exe Matplotlib】で
調べてみたら結構出てきました。
でも、理由が分かりません。
##■RecursionError: maximum recursion depth exceeded
訳【再帰エラー:最大再帰深さを超えました】らしいです。
はっ?あの、すみません、日本語で言ってもらえませんか?
日本語に訳したのに、意味が分からない日本語ってすごいですね。
コマンド画面の最終行に書かれていたので調べてみるとteratailで見つけました。
teratail:pyinstallerでのexe化に失敗します
これだけ見るとなんのこっちゃなんですが、
ベストアンサーで紹介されているstackoverflowの先に
対応方法が書いていました。(英語なので翻訳などしてください)
この部分に注目して下さい。
例えば、Hello.pyというPythonのファイルをExe化しようとしたとき
pyinstallerを実行すると、Hello.pyのファイルと同じディレクトリにHello.specという
specファイルが最初に出来、その後エラーが発生するとExe化は中止されます。
※specファイルはメモ帳とかにドラッグすると普通に中を見ることが出来ます。
そのspecファイルの一番最初の行に
import sys
sys.setrecursionlimit(5000)
と書き込み、上書き保存します。
コマンド画面に戻り、
今までは
pyinstaller Hello.py
だったのを
pyinstaller Hello.spec
で実行すると再帰エラーはなくなります。
##■UnicodeDecodeError: 'utf-8' codec can't decode byte 0x83 in position 130: invalid start byte
こいつはやばかった。ドドリアさんはもうすでに逃げ出していた。
どうも、デコードが上手くいってないエラーだというのはなんとなくわかる。
でもutf-8で記述しているし、特別へんてこりんなことはしてない。
大体それまで普通通り動いてたのです。
後々、もう少しコマンド画面をよく見れば、解決は早かったのかもしれないです。
さて、途方に暮れてteratailで質問しようと思い
質問文を書く前に、【Matplotlib EXE】で検索してみたが、それらしいものは無く、
ダメ元で【Seaborn EXE】で検索。これが大当たり。
teratail:python3のpyinstallerを使用したexe化について
回答者の方が回答内容を勘違いしていたのですが
そのあとに回答していた内容が大当たり。
本当にバグ取り作業並みの小ささ。
anaconda3\lib\site-packages\PyInstallerフォルダ内の
compat.pyファイルの370行目の
out = out.decode(encoding, errors='ignore')に書き換えてという指示。
質問者の方もこれを実施し、Exe化出来たとあります。
これPythonファイルの一部を書き換える作業です(画像矢印のところ)
ここを書き換えて保存。
もう少しコマンド画面をよく見ていればと思ったのは
この作業が終わってコマンド画面を見てみると、
ちゃんとそれっぽいのが出ていますね。
その後、pyinstallerで一旦.pyファイルを実行すると意外と通りました。
でも、念のためspecファイルで再実行し
ようやく思い通りのExeが出来た。
しかし、compat.pyの改修は本当にやばかった。
新しいバージョンになってこの辺りはちゃんと手入れされているのでしょうか。
そもそも、なんでMatplotlibと仲良くやってくれないのでしょうか。
でも、つくづく思うのはPython利用者が爆発的に増え、
それに伴うバグの質問や対応の情報量もとても豊富にあるので、
とても助かりました。
teratailの質問者の方、回答者の方
stuckoverflowの質問者の方、回答者の方
ありがとうございます。