Python3でGUI(WxPython)実行ファイル(pyInstaller)[Windows]

# PythonでGUI(WxPython)実行ファイル(pyInstaller)[Windows]

Pythonを使ってGUI表示の実行ファイルを生成する一連の方法を記載していきます。
GUIライブラリの中でwxPythonを使ったのはライセンス的に使いやすかったからです。

## ルート環境

ルート環境にAnacondaを使用しています。
実際に使うのは仮想環境上ですので、他のConda系の環境でも恐らく大丈夫かと思います。

> Anaconda
> https://www.continuum.io/downloads

## 仮想環境

### 仮想環境を構築

今回はテストで動作させたいので、ルート環境を使わずにwxenvという名前で新しい仮想環境を構築します。
コマンドプロンプト(Macならターミナル)で以下を実行
注意：2017年5月現在、PyInstallerがPython 3.5までにしか対応していない。

```cmd:command
conda create -n wxenv python=3.5.3
# Anacondaのセットで作成する場合
# conda create -n wxenv python=3.5.3 anaconda
# 作った環境を確認するときは
# conda info -e
# conda list -n wxenv
# 作った仮想環境を削除する時は
# conda remove -n wxenv --all
```

### 仮想環境のアクティブ化

以降の作業は、仮想環境上で行います。

```cmd:command
# Windows
activate wxenv
# 非アクティブ化
# deactivate

# Mac
source activate wxenv
# 非アクティブ化
# source deactivate
```

## WxPython

### WxPythonのインストール

> https://wxpython.org/

基本的にはwxPythonはPython2系らしいのですが、Phoenixバージョンという3系で動作するwxPythonを使います。
2017年4月からPyPIに対応したとのことで、下記コマンドを実行でインストール可能なようです。

```cmd:command
pip install wxpython
```

### WxPythonをテスト実行

適当な場所にテスト実行ファイルを下記の通り作って保存します。

```python:main.py
#! env python
# -*- coding: utf-8 -*-

import wx
import sys,os

if __name__ == '__main__':
    app = wx.App(False)
    frame = wx.Frame(None, wx.ID_ANY, "Hello World")
    frame.Show(True)
    app.MainLoop()
```

## PyInstaller

### インストール

```cmd:command
pip install pyinstaller
```

#### Windows
windowsの場合は、下記もインストール

```bat:windows
pip install pypiwin32
```

### 試しに使ってみる

まずは通常のコマンドプロンプトからの出力をします。

```bat:command
# 先程生成したテスト実行ファイル保存場所まで移動
cd (ファイル保存場所)
# PyInstaller実行（引数にオプションとして１ディレクトリ、１ファイル、コンソール非表示と前回の出力結果を消す命令）

pyinstaller main.py -D -F -w --clean
```

実行すると、
distというフォルダの中に生成されたexeファイルが生成されているはずです。

### specファイル

普通にpyinstallerを実行しても生成されますが、生成時の細かな調整を行いたい場合もあります。
その場合は、specファイルを作っておいて、そのファイルを都合の良い設定に書き換えたりしてから、pyinstallerにその設定を読み込ませて出力するという方法があります。

https://pythonhosted.org/PyInstaller/spec-files.html
https://pythonhosted.org/PyInstaller/usage.html#options

```cmd:command
# テスト実行ファイルの場所へ移動（既に移動済みなら不要）
cd (ファイル保存場所)
# specファイルの生成
# 対象のファイル名、生成するspecファイル名、オプションとして１ディレクトリ、１ファイル、コンソール非表示
pyi-makespec main.py -n="main" -D -F -w
```

上記を実行すると、main.specというファイルが生成されます。
このファイル内には、PyInstallerが使う各設定があり、ここを修正して外部ファイルを指定したりすることが出来ます。
もし、ここでうまく生成できない場合、1ファイルの部分（-F）を消してみてください。
また、一部の外部ライブラリはspecファイルにその旨を記載する必要がある場合もあります。
詳しくは[公式](https://pythonhosted.org/PyInstaller/spec-files.html)のAdding Binary Filesあたりを御覧ください。

```cmd:command
# specファイルを指定して実行
pyinstaller main.spec
```

これでdistというディレクトリにexeファイルが生成されたはずです。

### PyInstallerの作業ディレクトリについて

PyInstallerで実行する際は、下記の内容をPythonのファイル内に記載して実行ファイルのあるディレクトリを作業ディレクトリにしたほうが便利です。

```python:main.py
os.chdir(os.path.dirname(os.path.abspath(sys.argv[0])))
```

# 注意
Macの場合は、pythonではなくpythonwを使わないとwxPythonが動作しないようです。
http://www.sevencredit.com/2015/07/31/702/

# Matplotlib

MatplotlibをPyInstallerに登録してもそのままではQtのリンク関係で動作しないことが多いです。
対応策としては、`import matplotlib`の直後に別のバックエンドにすると通るはずです。

```
import matplotlib
matplotlib.use('TkAgg')
# 以下略
```

> https://github.com/pyinstaller/pyinstaller/issues/2857
> http://chick.g.hatena.ne.jp/allegro/20091009/p3

# WxFormBuilder

私の場合WxPythonの編集はwxFormBuilderを使ってます。
https://qiita.com/mm_sys/items/716cb159ea8c9e634300

<img width="1038" alt="スクリーンショット 2018-02-16 15.01.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/76058/e47b4b1c-95d4-6272-9ae9-750bbb775488.png">

# 別の方法

PyInstallerよりも、軽量・高速に動作する方法がありましたので別途記事を作成しました。

https://qiita.com/mm_sys/items/1fd3a50a930dac3db299