Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
77
Help us understand the problem. What is going on with this article?
@mamon

PythonプログラムをExeファイル化出来なくて1日費やしたときには

More than 1 year has passed since last update.

もし私がフリーザ様なら

地球は消えていたでしょう。
表題の件はそれくらい、久しぶりにハマりました。

さて、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の先に
対応方法が書いていました。(英語なので翻訳などしてください)

stuckoverflow:pyinstaller creating EXE RuntimeError: maximum recursion depth exceeded while calling a Python object

この部分に注目して下さい。
その1.png
例えば、Hello.pyというPythonのファイルをExe化しようとしたとき
pyinstallerを実行すると、Hello.pyのファイルと同じディレクトリにHello.specという
specファイルが最初に出来、その後エラーが発生するとExe化は中止されます。
※specファイルはメモ帳とかにドラッグすると普通に中を見ることが出来ます。

その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ファイルの一部を書き換える作業です(画像矢印のところ)
その2.png
ここを書き換えて保存。

もう少しコマンド画面をよく見ていればと思ったのは
この作業が終わってコマンド画面を見てみると、
その3.png
ちゃんとそれっぽいのが出ていますね。

その後、pyinstallerで一旦.pyファイルを実行すると意外と通りました。
でも、念のためspecファイルで再実行し
ようやく思い通りのExeが出来た。

しかし、compat.pyの改修は本当にやばかった。
新しいバージョンになってこの辺りはちゃんと手入れされているのでしょうか。
そもそも、なんでMatplotlibと仲良くやってくれないのでしょうか。

でも、つくづく思うのはPython利用者が爆発的に増え、
それに伴うバグの質問や対応の情報量もとても豊富にあるので、
とても助かりました。

teratailの質問者の方、回答者の方
stuckoverflowの質問者の方、回答者の方
ありがとうございます。

77
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
mamon

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
77
Help us understand the problem. What is going on with this article?