Windowsで環境を極力汚さずにPythonを動かす方法 (WSL利用 Windows10, version 1607以降限定)

## 【はじめに】
本記事の内容は教育や動作確認など、限られた用途にのみ有効です。
本手順で構築した環境では、情報の多いubuntu系Linuxの操作がある程度そのまま利用できるのが特徴です。
__ただし、USBドングルやGPUなどのHWにはアクセスできません。
また、この方法で構築した環境は、客先環境などには持っていけないのでご注意ください。__

## 【内容】
利用中のWindows PCの環境を極力汚さずにPythonをインストールして、開発や動作確認を行えるようにします。

## 【手順】
### 1. WSLの有効化
本手順ではWSL(Windows Subsystem for Linux)を利用して、Windows環境内にubuntuを利用できるようにします。
まずは、コントロールパネルから[プログラム] > [Windowsの機能の有効化または無効化] を選択し、表示されたダイアログの中から「Windows Subsystem for Linux」にチェックを入れて有効化します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454012/cae5fce0-bb95-5850-372e-258cf6472f16.png)

インストール後には再起動が必要になります。

### 2. ubuntuのインストール
「Microsoft store」を起動し[検索]から「ubuntu」を検索します。
いくつか候補が出てきますが、状況に応じて選択してください。
ここでは第一候補の「ubuntu」を選択し、インストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454012/080931f8-63dd-3587-91d0-1a1e72fab04f.png)

インストールが完了したら、スタートメニューから「ubuntu」を起動してください。
下記の画面でしばらく止まりますので、しばらくお待ち下さい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454012/33da71d9-cc82-2ee2-3d3c-3553fd59db6e.png)

画面が進みましたら管理者用のユーザとパスワードを設定してください。
パスワードはモジュールのインストール時などに必要になるので、忘れないようにしてください。
パスワード設定後、下記のように表示されたら準備完了です。

```出力結果.txt
Installation successful!
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

(ユーザ名)@(PC名): ~$
```

なお、インストールされた「ubuntu」はストアアプリとしてある特定のフォルダ内にインストールされ、中で使われるファイルはすべてそのフォルダ内に含まれます。
アンインストールすると全てのファイルが削除されるため、「ubuntu」内で行う操作によって環境を汚すことはありません。
(※「ubuntu」内からWindowsのファイルシステム(/mnt/c など)にアクセスする場合はこの限りではありません)

### 3. ubuntuのアップデート
最新のモジュールを利用するためにubuntuをアップデートします。
下記のコマンドを実行します。(updateおよびupgradeは時間がかかります)

```bash
# パッケージリストの更新
sudo apt update
# パッケージのアップデート
sudo apt upgrade -y
# 上記で保留されたパッケージのアップデート
sudo apt dist-upgrade -y
# 不要になったパッケージの削除
sudo apt autoremove -y
```
パスワードの入力を求められたら、2.で設定した管理者用のパスワードを入力します。


### 4. pythonおよびpipのインストール
下記のコマンドを実行してpythonとpipをインストールします。
インストールするpythonのバージョンによって多少コマンドが変わります。
(大量のパッケージをインストールするので時間がかかります)

#### 【python2の場合】
```
sudo apt install python python-pip -y
sudo pip install pip -U
```
#### 【python3の場合】
```
sudo apt install python3 python3-pip -y
sudo pip3 install pip -U
```
以上でpythonのセットアップは完了です。

【注意】
python2用の「pip」がインストールされている状況で「pip3」をインストールした場合、「pip3」コマンドを「pip」とエイリアスしてしまいます。
この場合「pip」コマンドを実行しても、実際には「pip3」コマンドが実行されてしまいます。
以下のコマンドを実行して、「pip」コマンドのバージョンを確認してください。
`pip -V`
表示された結果に「python 3」の文言がある場合は、pip3が動いています。
その場合は、「【python2の場合】」の「pip」コマンドは「pip2」と読み替えてください。




## 【補足】
### matplotlibのインストールとハマりどころ
matplotlibをインストールするには以下のコマンドを実行します。
#### 【python2の場合】
```
sudo pip install matplotlib
```
#### 【python3の場合】
```
sudo pip3 install matplotlib
```


### 「tkinter」モジュールのインストール
「ubuntu」環境に「tkinter」モジュールをインストールするために下記コマンドを実行してください。
tkinterはpythonにGUIを提供するモジュールです。
matplotlibのGUI表示(ウィンドウやボタンなどのUI)に必要になります。
#### 【python2の場合】
```
sudo apt install python-tk -y
```
#### 【python3の場合】
```
sudo apt install python3-tk -y
```

以上でインストールは完了です。
pythonを起動して`import matplotlib`を実行してエラーにならなければ成功です。

しかし、実際にグラフを表示しようと`plt.show()`などでGUIの画面を表示が必要な場面でエラーになります。
これはWSL上ではLinuxのGUI環境のXサーバが実行されていないためです。
X Window Systemではもともと別のサーバ上のディスプレイに画面を表示する機能が備わっていますので、その機能を利用してWindowsのクライアント上に画面を表示できるようにします。

### Windows環境にXサーバをインストールする
Windows上で実行可能なXサーバをインストールします。
Windows上で動作するフリーXサーバはいくつかありますが、中でも「VcXsrv」はパフォーマンスが良いと言われています。
そこで、下記URLの「Download」よりVcXsrvをダウンロードしてインストールします。
[【VcXsrv Windows X Server】](https://sourceforge.net/projects/vcxsrv/)

インストールが完了したら「XLaunch」を起動します。
ダイアログが表示されていくつか選択肢が表示されますが、全てデフォルトで「次へ」で進んで構いません。
最後に「完了」ボタンを押すとXサーバが起動します。


### 表示先ディスプレイの設定
「ubuntu」環境でXクライアントが利用するディスプレイの設定を行います。
ubuntu上で下記のコマンドを実行してください。

```bash:WSL1の場合
export DISPLAY=localhost:0.0
```
これで、Windows上で実行中のX Serverに対してGUI表示が出来るようになります。
なお、このコマンドはubuntuを起動する度に、毎回実行する必要があります。
.bachrcファイルなどに記載しておけば、この操作を省くことは可能です。

#### WSL2の場合 (2020年06月17日追記)
Windows10 2004以降ではWSL2が利用できるようになりましたが、ネットワークインターフェースの扱いが変わっています。
WSL1ではホストPCのIPとWSL内のIPは同じでしたが、WSL2では別のネットワークとして見なされています。
このため、環境変数 `DISPLAY` に設定する内容も変わってきます。
具体的には `localhost` の部分をWSLを実行しているホストPCのIPアドレスに変更してください。

```bash:WSL2の場合
export DISPLAY=<ホストPCのIPアドレス>:0.0
```
なお、WSL2では今後はGUIを扱えるようになる予定があるので、このような設定は不要になる可能性が高いです。


以上で、設定の変更は完了です。

### matplotlibのテスト
以下のコードを「vi」や「nano」などのエディタで保存して、pythonコマンドで実行してグラフが表示されるか確認してください。

【graph_test.py】
 (公式のサンプル集より [【CSD Demo】](https://matplotlib.org/gallery/lines_bars_and_markers/csd_demo.html#sphx-glr-gallery-lines-bars-and-markers-csd-demo-py))

```graph_test.py
import numpy as np
import matplotlib.pyplot as plt


fig, (ax1, ax2) = plt.subplots(2, 1)
# make a little extra space between the subplots
fig.subplots_adjust(hspace=0.5)

dt = 0.01
t = np.arange(0, 30, dt)

# Fixing random state for reproducibility
np.random.seed(19680801)


nse1 = np.random.randn(len(t))                 # white noise 1
nse2 = np.random.randn(len(t))                 # white noise 2
r = np.exp(-t / 0.05)

cnse1 = np.convolve(nse1, r, mode='same') * dt   # colored noise 1
cnse2 = np.convolve(nse2, r, mode='same') * dt   # colored noise 2

# two signals with a coherent part and a random part
s1 = 0.01 * np.sin(2 * np.pi * 10 * t) + cnse1
s2 = 0.01 * np.sin(2 * np.pi * 10 * t) + cnse2

ax1.plot(t, s1, t, s2)
ax1.set_xlim(0, 5)
ax1.set_xlabel('time')
ax1.set_ylabel('s1 and s2')
ax1.grid(True)

cxy, f = ax2.csd(s1, s2, 256, 1. / dt)
ax2.set_ylabel('CSD (db)')
plt.show()
```
【実行】
#### 【python2の場合】
```
python graph_test.py
```
#### 【python3の場合】
```
python3 graph_test.py
```

【結果】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454012/7f5c445d-8a06-2182-420b-39216d8e1135.png)

上記画面はX Serverを介してWindowsのウィンドウの一つとして表示されます。

以上でmatplotlibが使えるようになりました。

## 【その他】
WSL環境を構築するとコマンドプロンプトからWSL経由でLinuxコマンドが使えるようになります。
Linuxの便利なコマンドやツールが使えるようになるので、Linux系OSに慣れてる人にはオススメです。