WindowsにPyInstaller をオフラインインストールする

# はじめに
PyInstaller をpip でweb から自動的に取得してインストールするのではなく、パッケージをとってきてオフラインで手動インストールする方法についてまとめます。
なかなか目的にあうまとめかたをされている記事に出会えなかったのでまとめてみます。

ちなみに PyInstaller とは、PythonスクリプトをPythonがインストールされていない環境でも利用できるように配布用の実行ファイル（＊.exe）に固めてくれるライブラリです。便利なやつ。


### どうしてこんなことをしたいのか???
会社や学校によっては、アクセス可能なサイトやインターネット利用が制限されているところがあるかと思います。
そのような自由ではない環境下においても、Python を使いたい／使ってもらいたいと強く思うことがあるのです。


# やってみる前に
### 方針
下記制限の環境下において、できる範囲で最大限努力して目的を達成する。ズルはしない。

### 実行環境
* OS     : Windows 10, 64bit
* Python : 3.9.2 (執筆時の最新) 
* その他条件 :
    * webブラウザからインターネットにはアクセスできるが、閲覧禁止サイトがある
    * PCの利用制限があり、自由にソフトウェアをインストールしたりできない
    * ソフトウェアの通信に制限がある。今回でいうとpip（Python のパッケージマネージャ）でwebから各種パッケージを自動でインストールできない。
    * [PyPI](https://pypi.org/) にwebブラウザからアクセスできる。
        * PyPIとは、Python の各種パッケージが一元的に公開・管理されているサイト。本来 pip でパッケージをダウンロードしてくるところ。

### インストールが必要なもの各種
* Python 本体
* setuptools
* pywin32
* pyinstaller-hooks-contrib
* future
* pyinstaller

### インストールに使うコマンド
コマンド内容の詳細については本記事では説明しません。オプションなど気になる方は調べてみてください。

```
$ pip install --no-index --find-links=<download dir> <package>
```

うまくいかなければ下記で試してみてください。

```
$ python -m pip install --no-index --find-links=<download dir> <package>
```

# いざ、やってみる
## まずは、Python をインストールする
1. 下記サイトからPython のインストーラをダウンロード  
  https://www.python.org/downloads/
1. ウィザードに従ってインストールする  
  ※ここは、特別な手順ではないので詳細割愛します。  
  インストール時にPATH設定されるようにチェックをわすれずに。 

## PyInstaller のインストールを目指す
目的はPyInstaller をインストールして実行することができるようにすること。ただそれだけ。

pip を普通に使える環境であれば、

```
$ pip install pyinstaller
```

たったこれだけで済む話。
pip でインストールできる場合、依存関係にあるパッケージも自動的にインストールしてくれる。

しかし、世の中には pip で自由に通信できない環境があるのです。こまった。  
つまり、目的のPyInstaller だけでなく、きっとたくさんあるであろう依存関係にある各種パッケージも調べて、取得して、インストールするという手順が必要になるという。。。

## setuptools の最新版をインストール
Python をインストールしたら一緒に入っているはずだが、私の環境だとうまく認識されなかったのでアップデートがてらに最新バージョンをインストールする。

1. https://pypi.org/ にアクセス
2. 検索窓に `setuptools` と入力して検索
3. 3. 執筆当時の最新バージョンである `setuptools 54.1.2` をクリック
  ![img_pypi_setuptool.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565211/75c5cdf5-7053-da13-f402-580a57f6d8ef.png)

4. 左のNavigation から `Download files` をクリック
5. インストールするPCの環境とインストールしたPython のバージョンに合わせて、ダウンロードするものを選択
  `setuptools-54.1.2-py3-none-any.whl (785.0 kB)` を選択

  ![img_pypi_setuptool_dllist.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565211/92b2b786-ce6d-0de9-e5c6-879561929ae6.png)

6. 任意のフォルダにダウンロードする
  私は、 `C:¥tools` をいうフォルダを作成し、そこにダウンロードしました。
7. コマンドプロンプトを起動し、次のコマンドを実行

```
$ pip install --no-index --find-links=C:\tools setuptools-54.1.2-py3-none-any.whl
```

エラーなく完了すればOK 
※このあとも各種パッケージをダウンロード・インストールしますが、同様の手順なので、詳細は割愛しながら進めます。



## PyWin32 をインストール
* PyWin32とは、Windowns API をPython からアクセスできるようにするパッケージ。
* webで下調べをしていると、Windows にインストールする場合、Windowns API を扱うためにPyWin32 というパッケージのインストールが必要そう。  
たしかに内部的にWindows API を叩いてもらう必要があるだろうし納得の理由。
参考ページ：https://www.mutable.work/entry/python-exefile-pyinstaller

#### インストールする
1. https://pypi.org/ で `pywin32` と入力して検索
2. そうするといろいろ出てきますが、`pywin32 300` が目的のものなのでクリック
  よく似た名称のものが多いので注意！
3. 左のNavigation から `Download files` をクリック
4. インストールするPCの環境とインストールしたPython のバージョンに合わせて、ダウンロードするものを選択し、ダウンロード
  私の環境だと `pywin32-300-cp39-cp39-win_amd64.whl (9.2 MB)`が該当 
5. コマンドプロンプトから下記コマンドを実行し、インストール

```
$ pip install --no-index --find-links=C:\tools pywin32-300-cp39-cp39-win_amd64.whl
```


### pyinstaller-hooks-contrib をインストール
1. https://pypi.org/ で、`pyinstaller-hooks-contrib` と入力して検索
   執筆当時 `pyinstaller-hooks-contrib 2021.1` が該当のものなので、これをクリック
2. Download files > `pyinstaller_hooks_contrib-2021.1-py2.py3-none-any.whl` をダウンロード
3. コマンドプロンプトから下記コマンドを実行し、インストール

```
$　pip install --no-index --find-links=C:\tools pyinstaller_hooks_contrib-2021.1-py2.py3-none-any.whl
```


### future をインストール
1. https://pypi.org/ で、`pyinstaller-hooks-contrib` と入力して検索
  執筆当時 `future 0.18.2` が該当のものなので、これをクリック
2. Download files > `future-0.18.2.tar.gz` をダウンロード
3. コマンドプロンプトから下記コマンドを実行し、インストール

```
$　pip install --no-index --find-links=C:\tools future-0.18.2.tar.gz
```


### pyinstaller をインストール
いよいよ本来の目的の `pyinstaller` をインストールする

1. https://pypi.org/ で、`pyinstaller` と入力して検索
  執筆当時 `pyinstaller 4.2` が該当のものなので、これをクリック
2. Download files > `pyinstaller-4.2.tar.gz` をダウンロード
3. コマンドプロンプトから下記コマンドを実行し、インストール

```
$　pip install --no-index --find-links=C:\tools pyinstaller-4.2.tar.gz
```

最後までエラーなく終わればOK！！！


### pyinstaller が無事にインストールされているか確認
コマンドプロンプトから下記コマンドを実行する。正しくインストールされていれば、上記手順でインストールした各パッケージがバージョンとともに表示される。

```
$ pip list
```

pyinstaller ありますか？？　あれば成功です！おめでとうございます！お疲れさまでした。

## まとめ
### インストールしたもの
* Python 本体
* setuptools
* pywin32
* pyinstaller-hooks-contrib
* future
* pyinstaller

### インストール時のコマンド

```
$ pip install --no-index --find-links=<download dir> <package>
```

うまくいかなければ下記で試してみてください。

```
$ python -m pip install --no-index --find-links=<download dir> <package>
```


# 上記手順でエラーがでて進めなくなってしまった場合
私は上記の手順で、再現性を持って環境構築できることを確認しましたが、バージョンが変わったりすると依存関係が代わり、エラーがでることもあるでしょう。

### エラーメッセージ例
```
　　　　　　：
$ ERROR: Could not find a version that satisfies the requirement pyinstaller-hooks-contrib>=2020.6 (from pyinstaller==4.1) (from versions: none)
$ ERROR: No matching distribution found for pyinstaller-hooks-contrib>=2020.6 (from pyinstaller==4.1)
　　　　　　：
```

### エラーを解消するために
基本的には下記手順をエラーがでなくなるまで根気強く繰り返す。

1. [PyPI](https://pypi.org/) から該当パッケージを探す  
  上記エラー例なら`pyinstaller-hooks-contrib`
2. 該当ファイルをダウンロードしてコマンドでインストール  
  上記エラー例なら下記コマンドを実行

```
$ pip install --no-index --find-links=C:\tools pyinstaller_hooks_contrib-2021.1-py2.py3-none-any.whl
```


# さいごに
上記手順により、pip で自由にパッケージインストールできない束縛を受けている環境においても、PyInstaller をインストールすることができました。
PyInstaller の使い方は pip で自動的にインストールする場合と全くかわりませんので、説明は別の良記事におまかせします。
それでは、よい PyInstaller ライフをお楽しみください！