【悲報】PyInstallerさん、300MBのexeファイルを吐き出すようになる



表題の通り、PyInstallerを使って出力したexeファイルがとにかく巨大に膨れ上がる現象に悩まされました。

これ、めちゃくちゃ起動遅くなるし、原因不明だし、ほんと参ってたんですが、解決しましたので、メモ書き。

さっと作って、さっと配布したいのに一々こんなところで悩みたくない方向けにその他のPyInstallerのトラブルもまとめてます。

PyInstaller出力のexeファイルの巨大化

これはマジでヤバいです。普通に作ったはずなのに出力したら300MBもあります。 --onefile を指定した場合の話なんですが、普通 --onefileしますよね。

どう考えても使っているモジュールの合計容量をはるかに超えてるので最初はサッパリ意味が分かりませんでした。

exeファイルが巨大化する原因

これはPyInstaller自体の仕様の問題です。

コマンドを出した環境のPathにあるモジュールは根こそぎバンドルしに行くという仕様が原因のようです。

解決策その①

一応回避方法として --exculude コマンドが用意されているようです。

--exculude は複数回指定できるオプションなので、複数のモジュールのバンドルを拒否したい場合はこうなります。

あんまり普段から環境の分離とか意識してない方は恐らくこう思うはずです。

やってられるかっ!

解決策その②

上でもう答え書きましたが、PyInstallerを実行する環境だけ、最低限のモジュールのみが含まれた仮想環境を用意してやると解決できます。

一々全部除外していくのとかめんどくさすぎますから、普通にこの方法が最短だと思います。

venvなら、

condaなら

仮想環境のアクティベートが完了したら必要なものだけインストールします。

注意が必要なのは必ず「pipで入れる」ということです。
pipじゃなくてもいいのかもしれませんが、とりあえず conda install だけはやめましょう。(理由は後述)

ここまで来たら普通にPyInstallerでパッケージングするだけですね。

Anaconda環境はヤバい

さて、肥えに肥えた超絶デブexeファイル、300MBというとこですが、どう考えても道理に合わない肥え方です。

明らかに目に見える(pip list とかで確認できる)範囲のモジュールの容量を超えているんじゃないのか?という疑問。

結論から言うと、犯人はAnaconda環境でpandasをインストールした時にdependencies(依存関係)として勝手についてくるMKLというモジュールがビビるくらい容量を取っています。

つまりAnaconda環境でpandas (もしくはnumpyも?)をインストールしている方はまず間違いなくPyInstallerを使うと、出力されるexeは軽く200MBは超えていきます。

こいつはpipでインストールするとついてきません

Anaconda環境のDLLエラー

更に厄介なことにクリーンな状態の仮想環境を用意したとしても、Anacondaに依存した環境のPythonモジュールを使って各モジュールを再度インストールするとPyInstallerでexe化した後にdll import error 的なヤツに陥ることがあります。

こんなヤツです。

もうこうなったらそれこそエラー回避するだけで一日かかりますので、Anacondaを捨てた方がいいです。

具体的にはAnacondaじゃないPython環境を一個作っておくという事ですね。

システムの環境変数関係からもAnacondaの配下Pathは全て無効にします。
消したら戻すときめんどくさいので、適当に余分なマーク付けてpathを無効化するくらいでいいと思います。

PyInstallerで陥りがちなその他の問題

TypeError: an integer is required

3.8upのPythonを使っていた際に遭遇。

解決:Python3.8を捨てる

特にこだわりがなければ3.8を一旦捨てましょう。3.8独自の書き方を使ってたら直してください。3.7台は全然使えます。

海外フォーラムでも「直ったよ」って言ってるヤツもいれば「まだエラー出るやんか!」って言ってるヤツもいてまだまだカオスです。

一応公式アナウンス的には直ったと言ってるようですが、僕はそう言われてる後にこのエラーに遭遇しました。

ImportError: DLL load failed

Anaconda環境で遭遇。
上でも述べましたがPyInstallerはAnacondaから切り離された環境で使うのがベストです。

敢えていばらの道を進みたい方がいたら下に解決法を載せておきます。

解決:C:~Anaconda3Librarybin をPathに追加

とりあえず、Pathが通ってないだけです。

これに関しては、ね。

AttributeError: 'str' object has no attribute 'items'

何を言っているのかサッパリわからない系の問題

解決:setuptoolsが古い

アップグレードしましょう。

Cannot find existing PyQt5 plugin directories

GUIアプリを作ってるときに出てくる問題。

解決:PyQt5インストール

そもそもPyQt5がなかっただけならこれで解決しますが、たまにあるのにこのエラーが出る時があります。

これもね、Anaconda環境の話ですが、絶対PyQtあるのにこのエラー出て悩みました。

その場合多分こんな感じで下にPathが書いていると思います。

とりあえず、なんも考えず、その通りのディレクトリ構造を作ったら解決しました。

という階層に何も入れず、ただ空のフォルダを作成するだけです。

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x83 in position 130: invalid start byte

見飽きましたね。

文字コード系のエラーです。

解決①:Shift-JIS 系でファイルを保存しない

Shift-JISはWindows標準の文字コードですので、メモ帳とかで編集したり保存するとディフォルトでその形式で保存されます。

心当たりがあったらやめましょう。

解決②: compat.py の修正

compat.py がエラーを起こしてますので、そこを修正すると治ります。

こんな感じのディレクトにcompat.pyがあります。

の箇所を探します。2か所あります。

僕のファイルの状況では427行目、574行目の2か所でした。

該当箇所を以下のコードに置き換えます。

これで文字コードエラーは無視されます。

PyInstaller 問題 - 総括 -

余分な時間取りたくない方はメモ必須です。

また何か起きたら