【WSL】Python+VSCode環境構築

# 紹介すること
- 環境構築に必要なミドルウェアのインストール
- anyenvを使った環境構築
- poetryの設定
- VSCodeの設定
- デバック方法
- 実行方法

# 環境構築
Pythonのバージョン管理ツール`pyenv`とバージョン管理ツールを管理する`anyenv`のインストール方法やVSCodeの設定方法を紹介します。

## ミドルウェアのインストール
Linuxシステムアップデート

```bash
$ sudo apt update && sudo apt upgrade -y
```

Pythonインストールに必要なミドルウェアのインストール

```bash
sudo apt install -y zlib1g-dev libssl-dev libbz2-dev libsqlite3-dev libffi-dev \
    build-essential libreadline-dev tk-dev liblzma-dev libgdbm-dev libdb-dev unzip
```

## anyenvのインストール
下記コマンドを実行して`anyenv`をインストールします

```bash
$ git clone https://github.com/anyenv/anyenv ~/.anyenv
```

### .bashrcにパスを追加
`~/.bashrc`の下部に以下を追加します。

```bash:~/.bashrc
export PATH="$HOME/.anyenv/bin:$PATH"
eval "$(anyenv init -)"
```

変更を反映

```bash
$ source ~/.bashrc
```

インストールされたか確認

```bash
$ anyenv -v
anyenv 1.1.4
```

### 初期化
`anyenv`を初期化します。

```
$ anyenv install --init
```

### anyenv update pluginの導入
`anyenv`で管理する`pyenv`や`nodenv`などをアップデートする際

```bash
$ mkdir -p $(anyenv root)/plugins
$ git clone https://github.com/znz/anyenv-update.git $(anyenv root)/plugins/anyenv-update
$ anyenv update
```

## pyenvとPythonのインストール
### pyenvのインストール
`anyenv`を使って`pyenv`をインストールします。

```bash
# pyenvのインストール
$ anyenv install pyenv
# ターミナルを再起動する
$ exec $SHELL -l
```

### Pythonのインストール
`pyenv`でインストールできるPythonのバージョンを確認します。

```bash
$ pyenv install --list
...
  3.9.9
  3.10.0
  3.10-dev
  3.10.1
  3.11.0a3
  3.11-dev
...
```

現段階で最新の`3.10`系がインストールできそうです。

`3.10.0`のインストール

```bash
# 3.10.0のインストール
$ pyenv install 3.10.0
# 切り替え可能なバージョンの確認
$ pyenv versions
# インストールした3.10.0に切り替え
$ pyenv global 3.10.0
```

インストールされたか確認

```bash
$ python -V
Python 3.10.0
```

`3.10.0`以外も同様に`pyenv install 3.xx.xx`でインストールし、`pyenv global 3.xx.xx`で切り替え可能です。

### pipのアップグレード

```bash
$ python -m pip install --upgrade pip
```

## poetryのインストール
下記コマンドで`poetry`と後から使う`flake8`と`autopep8`、`isort`もついでにインストールします。

```bash
# インストール
$ pip install poetry flake8 autopep8 isort
```

インストールされたか確認

```bash
$ poetry -V
Poetry version 1.1.12
```

### poetryの設定
初期設定だとプロジェクトごとに`/home/user/.cache/pypoetry`配下に実行環境`.venv`が配置されます。しかし、VSCodeでデバックやコードジャンプを行う際プロジェクトごとにPATHを通す必要があり手間になっていまします。

そこで、各プロジェクト配下に`.venv`が配置されるように設定を変更します。

```bash
$ poetry config virtualenvs.in-project true
```

反映されたか確認
`virtualenvs.in-project = true`であればOKです

```bash
$ poetry config --list
cache-dir = "/home/xxx/.cache/pypoetry"
experimental.new-installer = true
installer.parallel = true
virtualenvs.create = true
virtualenvs.in-project = true # ここがtrueであればOK
virtualenvs.path = "{cache-dir}/virtualenvs"  # /home/xxx/.cache/pypoetry/virtualenvs
```

## サンプルプログラムのダウンロード
poetryの動作確認を行うため、サンプルコードをダウンロードします

```bash
$ git clone https://github.com/sattosan/sample-poetry.git
$ cd sample-poetry
```

### 依存関係のインストール
依存関係をインストールした仮想環境を作成します

```bash
$ poetry install
```

## VSCodeの設定
WSLからVSCodeを開きます。

```bash:./sample-poetry
$ code .
```

`Command ‘code’ not found`となった場合は下記を参考にしてください
https://snowsystem.net/other/windows/vscode-wsl-run-error/

### 拡張機能のインストール
マーケットプレースから下記拡張機能をインストールします。

- Pylance
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130670/f686cd04-721a-bc96-84a8-ac4755b3b4aa.png)

- Python
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130670/937e7d0d-799b-280d-4612-4a80473af913.png)

### settings.jsonの変更
こちらを参考に`settings.json`を開きます
https://qiita.com/y-w/items/614843b259c04bb91495

json内に追加します。

```json
  "editor.codeActionsOnSave": {
    "source.organizeImports": true
  },
  "editor.formatOnSave": true,
  "python.linting.pylintEnabled": false,
  "python.linting.flake8Enabled": true,
  "python.linting.lintOnSave": true,
  "python.linting.flake8Args": ["--ignore=E501"],
  "[python]": {
    "editor.tabSize": 4
  }
```

内容は下記の通りです

- import文の並び替え
- lintに`flake8`
- ファイル保存後自動フォーマット
- 1行79文字制限を無視
- タブのスペース数を4


### 自動フォーマットされるか確認
main.pyをVSCode上で開き、修正はありませんが保存します。

```python:修正前
from dateutil.relativedelta import relativedelta
import datetime
def main():
    for i in range(10):
        today=datetime.date.today()
        print(today)
        next_month_date=today + relativedelta(months=+i)
        print(next_month_date)
if __name__=='__main__':
    main()
```

保存後、下記のようにフォーマットされるはずです

```python:修正後
import datetime

from dateutil.relativedelta import relativedelta


def main():
    for i in range(10):
        today = datetime.date.today()
        print(today)
        next_month_date = today + relativedelta(months=+i)
        print(next_month_date)


if __name__ == '__main__':
    main()
```

### 実行
VSCodeで`Ctrl+Shift+@`でターミナルを起動します。(WSL上でもOK)
ターミナル上で下記を実行して、動作確認を行います。

```bash
$ poetry run python main.py
```

![スクリーンショット 2021-12-13 170724.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130670/5fcf0d25-553c-8deb-5494-6575ac11c442.png)

### デバック
拡張機能`Python`をインストールしたことでエディタ上でデバックが可能です。

試しにフォーマット済みのmain.pyの8行目にプレイクポイントを貼ってみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130670/0e89f067-2076-bd85-325b-5ef914fe8e2e.png)

F5キーを入力するとデバックモードが起動し、ステップオーバーやステップインで実行を追えます。

サイドバーの変数欄で、現在どのような値が入っているか確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130670/143dc7fe-2238-894c-9f33-642dd2e28466.png)

### コードジャンプ
`Ctrl`キーを押しながらクリックすることでコードジャンプが可能です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130670/923e0b91-52fc-3a25-64cc-e2d44539a037.png)