Pyinstallerの使い方、いろいろな相性まとめ

以下の組み合わせでPyinstallerが動くことを確認しましたので報告します。

#環境

- Windows10 Home, Anaconda3
- python3.7.x
- pyinstaller 3.5


よく使うコマンド(自分用)（具体化は甘えか...）

``` anaconda用、コンソールなし
pyinstaller main.py --exclude-module=PyQt5 --noconsole
```
``` コンソールあり、まとめる
pyinstaller main.py --onefile
```
``` コンソールなし、まとめる
pyinstaller main.py --onefile --noconsole
```
*onefile化は一時ファイルを作成する必要があり低速化を招くので注意。[出典](https://pyinstaller.readthedocs.io/en/stable/operating-mode.html#bundling-to-one-file)


#上手なpyinstallerの使い方？
以下の操作を行うことでいくつかの利点がある。
- 無駄なパッケージを読み込まないでよくなる
- ファイルサイズが小さくなる
- exeファイルを高速に作成可能になる

1. 仮想環境（venv）用意する
仮想環境は種類があるが、python公式のvenvがいいと思う。[参考](https://qiita.com/KRiver1/items/c1788e616b77a9bad4dd)

VScodeで仮想環境を作ろうと思ったら、作業ディレクトリに.venvが作成されなかった。
-> コマンドプロンプトから直接作成する必要がある。

```作成方法.
python -m venv 仮想環境名
```

```起動方法.
./仮想環境のディレクトリ名/Scripts/activate 
```
と入力すればおっけ。
2. pandas, numpy などの巨大なパッケージに注意[参考](https://medium.com/lsc-psd/pyhon-py-exe%E5%8C%96-%E8%BB%BD%E9%87%8F%E5%8C%96-%E9%AB%98%E9%80%9F%E5%8C%96-%E5%BF%98%E5%82%99%E9%8C%B2-pyinstaller-py2exe-4cd7c5f70c99)

3. pyinstaller起動・ファイル作成 


#バージョンの確認方法
python

```
python -V
```

pyinstaller

```
pyinstaller -v
```

#動作確認OK!!
(including: pyautogui, numpy)
python3.6.5(python-3.6.5-amd64.exe), pyinstaller3.4, numpy1.15.4

|python ver|pyinstaller ver|numpy ver|
|:-----------------|------------------:|:----------------:|
|3.6.9(Anaconda3)| 3.4| 1.15.4|
|3.6.9(Anaconda3)| 3.4| 1.16.4|
|3.6.9(Anaconda3)| 3.4| 1.16.5|
|3.6.9(Anaconda3)| 3.5| 1.16.5|
|3.7.3(Anaconda3)| 3.5| 1.16.5|
|3.7.3(Python3)| 4.0| 1.19.2|

(with --onefile, --exclude-module PyQt5)


#動作失敗
(including: pyautogui, numpy)

|python ver|pyinstaller ver|numpy ver|
|:-----------------|------------------:|:----------------:|
|3.6.5| 3.4| 1.17|
|3.6.6| 3.5| 1.17|
|3.8.6| 4| |

##エラーメッセージ

- pynputとpyinstallerの相性
pynput 1.6.8と pyinstaller 1.19.2で動作確認
https://stackoverflow.com/questions/63681770/getting-error-when-using-pynput-with-pyinstaller

- pyinstaller と numpy の相性が合わない[^1]

```
>ImportError: numpy.core.multiarray failed to import
Traceback (most recent call last):...
...
ModuleNotFoundError:No module named'numpy.random.common'
[]Failed to execute script ***
```

![error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349681/1fef1b0f-1345-7c0c-2629-825fd3b643ff.png)
[解決法]
わたしの場合は、python3.6.5(python-3.6.5-amd64.exe), pyinstaller3.4, numpy1.15.4にしたら解決できました

- PyQt5が読み込めていない

```
Exception:
            Cannot find existing PyQt5 plugin directories
            Paths checked: C:/qt64/qt_1544645195969/_h_env/Library/plugins
```
[解決法]
Pyinstallerはデフォルトで要らないモジュール・パッケージまで含めてしまうようです。[^2]
PyQt5を使用していないなら、これを含めなければエラーが出てきません。（根本的な解決ではありませんが…）

```
pyinstaller main.py --exclude-module=PyQt5
```

- configparserでうまくファイルが読み込めない!
 - 作業ディレクトリを確認する
 - コマンドプロンプトから開く場合、プロンプトに表示されているところが作業ディレクトリになる。 



#試すべきこと

- numpy update

- 他環境のnumpyを参照していないか

```
 import sys
 sys.path
```



# コードごとの容量の違い(pyinstaller version 3.4 + python)


```pyinstaller 任意.py
```

```A.py
print('a')
```

```B.py
import tkinter
print('a')
```


|        |       A |    B    |
|:-----------------|------------------:|:------------------:|
| 容量             |              13.8 MB  |       20.7 MB       |
| spec file           |     -        |       Aと同じ       |

```C.py
import tkinter as tk
root = tk.Tk()
root.mainloop()
```

```D.py
import tkinter as tk
root = tk.Tk()
for i in range(30):
    button = tk.Button(text = '{}'.format(i))
    button.pack()
root.mainloop()
```

|        |       C |    D    |
|:-----------------|------------------:|:------------------:|
| 容量             |  20.7 MB (21,777,172 バイト)  |       20.7 MB (21,777,260 バイト)       |
| spec file           |     Aと同じ        |       Aと同じ       |
|MKLを入れていない環境|20.0 MB (21,038,144 バイト)||


- pyinstaller 任意.py --onefile


|        |       C |    D    |
|:-----------------|------------------:|:------------------:|
| 容量             |  9.15 MB (9,603,958 バイト)  |     9.15 MB (9,600,748 バイト)        |
| spec file           |     Aと同じ        |       Aと同じ       |




# MacBookで使う際の注意点
2018年の段階ではPyinstallerで作成されたExeファイルを開くと滲む不具合？があるようです。
解決法は次のURLを参照→https://qiita.com/cheuora/items/39b3203400e1e15248ed


#参考
[^1]: Standalone Executable Created by PyInstaller Can't Import Numpy
[1]. [Standalone Executable Created by PyInstaller Can't Import Numpy](https://stackoverflow.com/questions/54296556/standalone-executable-created-by-pyinstaller-cant-import-numpy)
[^2]: [Pyinstaller automatically includes unneeded modules]
[2]. [Pyinstaller automatically includes unneeded modules](https://github.com/pyinstaller/pyinstaller/issues/2652)

完全に趣味でPythonをいじっているので、間違っていることがあったらごめんなさい。
細かいことでもいいので、コメント欄でご指摘いただけると、わたしの勉強になりますので、お気軽にどうぞ～。

以上