VSCodeでPython書いてる人はとりあえずこれやっとけ〜

## はじめに
Pythonはコードが汚くなりがち（個人的にそう思う）
そんなPythonくんを快適に書くための設定を紹介します。

## 拡張機能編
ここでは **Pythonを書きやすくするため** の拡張機能を紹介していきます。

### 1. [Error Lens](https://marketplace.visualstudio.com/items?itemName=usernamehw.errorlens "Error Lens")
<img width="500" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/149aac1a-8741-bd1c-c5e2-986ed1c3832b.png">

#### before
「コード書いたけど、なんか波線出てるよ💦」
記述に問題があった場合、デフォルトでは波線が表示されるだけ。。。
<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/fa5391e8-d28e-ea92-872d-e55a5ddd2355.png">


#### after
Error Lensくんを入れることによって **波線だけでなくエディタに直接表示される**。
はい、有能〜
<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/0e5158c0-7f3a-e064-d90d-cdffee4e4190.png">

### 2. [indent-rainbow](https://marketplace.visualstudio.com/items?itemName=oderwat.indent-rainbow "indent-rainbow")
<img width="500" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/51a1d911-e636-192c-9b27-702cfc68cc9e.png">

#### before
Pythonくんは **インデントでスコープを認識している**。
`for` の `f` から下に線が伸びてるけど、ちょっと見にくいなぁ
<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/7cfe88fd-7f8f-2758-a6e0-cc12489c1b46.png">


#### after
色が付いてちょっと見やすくなった！
<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/7509411e-c753-5cad-a6b8-60763b783a1a.png">

### 3. [Trailing Space](https://marketplace.visualstudio.com/items?itemName=shardulm94.trailing-spaces "Trailing Space")
<img width="500" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/45f80d17-f140-8d4b-8b62-c37c9f0c8cd3.png">


#### before
一見、普通に見えるコード
<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/0cd28577-4c0e-eb95-090e-d854a88ad4ef.png">

#### after
末尾にある無駄なスペースを可視化できる！
不要なものは消しましょうね〜
<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/f802fdab-1705-2484-ee84-0b57c2b33729.png">

### 4. [autoDocstring: VSCode Python Docstring Generator](https://marketplace.visualstudio.com/items?itemName=njpwerner.autodocstring "autoDocstring: VSCode Python Docstring Generator")
<img width="500" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/4131c958-23c8-4b08-6f9c-1666df999090.png">

三点引用符を使って関数などの説明を書くときにdocstringが自動生成される！！！
有能すぎぃ〜
<img width="450" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/72e8ccb4-078f-77fb-a00a-bfff058f84b3.png">

<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/10f6a104-5ec2-80af-bae5-6281799a2a08.png">

## 基本設定編
ここでは **VSCode自体の設定** を紹介します。
プログラミングをするに当たって必要になってくるものです。

### Insert Final Newline
ファイルの保存時、最終行に改行を自動で入れてくれる機能
プログラミングしてるなら必須だよね〜
<img width="500" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/a42bc885-0fe0-dad2-f0d0-bc47b48b2187.png">

https://teratail.com/questions/71778?sort=1

### Trim Trailing Whitespace
不要な末尾の空白を自動で削除してくれる機能
↑で紹介した拡張機能「Trailing Space」の削除版
<img width="500" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/7cc659bd-4357-6b37-c6a5-ff8cca132eb0.png">

## Pythonの設定編
ここでは **Pythonを最低限綺麗に書くため** の設定を紹介します。
自分はいつも **flake8, black, isort, mypy** を使用しています。

### black
Pythonのフォーマッタである **black**
通常は `black ファイル名` でコードの整形ができるが、VSCodeに設定すると自動整形することができる。

まずは black のインストールから
```bash
$ pip install black
```

次に、blackが実行できるか確認する。
テキトーにファイルを作る。
<img width="250" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/7bd9fbc7-5f04-1a3a-dc14-870d950a517d.png">


blackをかけてみる。
```bash
$ black black_test.py 
reformatted black_test.py
All done! ✨ 🍰 ✨
1 file reformatted.
```

ちゃんと整形されていればOK
<img width="250" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/7066e637-4f72-38a2-53eb-607ef55be276.png">

blackのコマンドのパスを確認する。
windowsの場合は、whichじゃなくてwhereかなー。
```shell
$ which black
/Users/macuser/Library/Python/3.9/bin/black
```

VSCodeの設定で `black` と検索する。
**Black Path** に ↑で確認できたパスを入力する。
**Black Args** の **Add Item** を押して `--line-length=79` を入力して **OK** を押す。

<font color="DarkGray">line-lengthを設定する理由としては、後述するflake8との競合を回避するため。<br> Pythonのコーディング規約で一行の文字数は原則79文字と決まっている。<br >79文字以上に設定する場合はline-lengthの値を変更すると良い。<br> 特に指定がない場合はデフォルトの79文字に設定する方が良い。</font>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/fd132604-8efb-296d-c461-cec931363813.png)

次に `python formatting provider` を検索する。
デフォルトで `autopep8` になっている項目を `black` に変えればOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/4e84437c-878a-fd85-8ed6-34d56927ab85.png)

あとはファイルを整形前に戻して、右クリック。
**Format Document** （日本語の場合: **ドキュメントのフォーマット**）をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/925d995b-4bdd-7941-90c9-b279bb9b9c36.png)

ちゃんと整形されればOK
<img width="250" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/7066e637-4f72-38a2-53eb-607ef55be276.png">

整形処理をファイル保存時に自動で実行するように設定することも可能。
`format on save` と検索し、チェックボックスにチェックをつける。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/3da6f0de-3953-262e-03f0-a9d4229b29dd.png)

これでファイル保存時に自動でblackが実行されるようになる。完璧。

### flake8
Pythonのリンター `flake8`
これもVSCodeで設定できるので紹介します。

まずはインストールから。
```bash
$ pip install flake8
```

また同じようにテキトーにファイルを作る。
<img width="250" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/ae3b97e5-98f7-bf3e-9c3a-8950ab835807.png">

実行してみる。
```
$ flake8 flake8_test.py
flake8_test.py:1:1: E265 block comment should start with '# '
flake8_test.py:5:2: E225 missing whitespace around operator
flake8_test.py:6:2: E225 missing whitespace around operator
flake8_test.py:7:2: E225 missing whitespace around operator
```

はい、沢山怒られている。

flake8のパスを確認する。

```
$ which flake8
/usr/local/bin/flake8
```

`flake8 path` と検索して↑で出てきたパスを入力する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/7ca17434-713b-b4ec-7389-a375995322ea.png)

次に `flake8` で再検索をかけて、メッセージタイプの設定を行う。
flake8はあくまでリンターであるので、警告レベルにするために **W, F, E** 全て `Warning` にすると良い。
<img width="500" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/77c642d8-2b13-e002-ed0c-0b337e909abc.png">

そして、先ほどのファイルを見てみると、、、、
拡張機能編で紹介した **Error Lens** との相性がバツグンで、どこが汚いコードなのか一目瞭然。有能。
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/133d9cd2-3fdd-6285-7277-3bc56eda14d9.png">

前述したblackの文字数を調整する場合は `flake8 args` と検索をかけて **Add Item** をクリックし、**--max-line-length** の値を設定してあげる。
デフォルトでは79文字のため、black側で79文字に設定した場合は不要。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/b1445b39-0e85-df72-c157-b2d7a8abd765.png)

### isort
importの順番はPythonのコーディング規約で決まっている。
> import文 は常にファイルの先頭、つまり モジュールコメントや docstring の直後、そしてモジュールのグローバル変数や定数定義の前に置くようにします。
>
> import文 は次の順番でグループ化すべきです:
>1. 標準ライブラリ
>2. サードパーティに関連するもの
>3. ローカルな アプリケーション/ライブラリ に特有のもの
>
>上のグループそれぞれの間には、1行空白を置くべきです。
>
> https://pep8-ja.readthedocs.io/ja/latest/#import

でもこれを考えてコードを書くのはめんどくさいので、isortというフォーマッタに任せてしまう。

とりあえず、インストール & パス確認
```bash
$ pip install isort
$ which isort
/usr/local/bin/isort
```

まずはテキトーなコードを書いていく。
flake8に「importしてるのに使ってねえじゃん」って怒られてるけど、サンプルなので まあいい。
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/6384ffc4-943e-a502-44d2-b7d23aebb8be.png">


isortの実行
```bash
$ isort isort_test.py
Fixing /Users/macuser/Desktop/isort_test.py
```

ちゃんと整形されればOK
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/6de74ce2-2c21-e522-533b-7dbeb14e3b0b.png">

こいつもVSCodeで設定していくぅ
`isort path` と入力して↑で確認したパスを入力する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/b5b032ce-e92b-cefd-79d6-76c9df6525d1.png)

とりまこれでOK

次に保存時に自動で実行される設定をする。
`code action on save` と検索をかけ、一番上に出てきたEditorの設定の **Edit in settings.json** をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/ef5ddff9-674e-fc7f-9ba2-92a6f11ca803.png)

設定のjsonファイルが開かれるので、**editor.codeActionsOnSave** のキーに以下を追加する。
```json
{
  "source.organizeImports": true
}
```

最終的にこのようになっていればOK
```json
    ...

    "python.sortImports.path": "/usr/local/bin/isort",
    "editor.codeActionsOnSave": {
        "source.organizeImports": true
    }
}
```

これで **保存時にisortが自動で実行される**。かんぺきぃ。

### mypy
mypyはPythonの型ヒントチェッカー
これはどちらかというと初心者向けではないが、あった方が綺麗（というか分かりやすい）コードが書けるのでよい。
型ヒントを知らない人は調べてください。より良いコードが書けるので。

とりま、インストールして、パスの確認
```bash
$ pip install mypy
$ which mypy
/usr/local/bin/mypy
```


同じように mypyの設定をしていくぅ！
`mypy path`で検索をかけて、パスを入力する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/d586042f-0642-0948-276c-b26e50ac1b22.png)

続いて、`mypy enable` にチェック〜
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/042c3700-6796-c189-5e78-ebd010b2244f.png)

メッセージレベルは **information** でいいかなって感じ。
mypyにひっかかってもコード自体に問題はないし、規約に反してるわけでもないので。
<img width="450" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/064c0a4b-a412-f9b4-ff14-288809e92f7d.png">

ここまで設定できれば、とりあえず型チェックが効く。
**aという変数に文字列入れたのに、数字入れるなよ**ってmypyさんに怒られてる図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/2dee4ec6-1b96-cb36-8451-b3499ea122f7.png)

あとは `mypy args` で色々チェック方法をカスタムできるよ〜
自分の設定を晒しておく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/3fef1988-50f4-b77e-2fbd-eb6b6ec75c12.png)

| 引数 | 説明 |
| -- | -- |
| --warn-return-any | 返り値は正確に明示しないとユルサナイ |
| --no-implicit-optional | 型を明示した変数に None を入れるのをユルサナイ |
| --disallow-untyped-calls | 返り値が明示されていない関数を呼び出すのをユルサナイ |
| --disallow-untyped-defs | 関数に返り値の型を明示しないのをユルサナイ | 
| --ignore-missing-imports | importしたライブラリ元に型明示がないのは仕方ないよね |
| --follow-imports=skip | importしたライブラリの型チェックは行わないよ |

自分がPython書いてきて、↑の設定が自分に合ったものだった。
他にも色々設定できるので、見てみるといいかも〜
https://mypy.readthedocs.io/en/stable/command_line.html

この設定をした場合、このようなコードは怒られる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/b9ad80f6-be9e-49a2-94a7-3c5274224494.png)

こうすれば怒られない。
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437282/b41f9e5a-f82d-4128-7f26-1117cd1e585c.png">


以上が、black, flake8, isort, mypy の設定でした〜
それでは良いPythonライフを〜

### 付け足し
Pythonについての情報共有ができるLINEのオープンチャットを運営しています。
完全匿名で参加できるので、よろしければぜひ。

オープンチャット「Python」

https://line.me/ti/g2/clUQPZkyNUAnT2n3Yf87KpYv6snMN-PQXGKheg?utm_source=invitation&utm_medium=link_copy&utm_campaign=default