[Python / linting] 最近の VSCode linting の設定方法 - for Mac / Windows (WSL)（2023/12/05）

# 1. 概要

今までVSCodeの `setting.json` に書いてきた Python linter 関連の設定方法が **非推奨になっている** ことに気がついた。

そこで、新しい設定方法を調べて以下に書きました。

この記事の対象のlinterは以下の通り。

- flake8
- black
- mypy
- isort
- ruff (_**2023/12/05 追記!!**_)


# 2. 結論

- `setting.json` の書き方が変わるよ
- `flake8`, `black`, `mypy`, `isort`, `ruff` については、 `pip install` とかしなくていいから、VSCode拡張を入れてね


# 3. 実行環境

以下の環境で動作確認したよ。

~~気付いたのだけど、本記事での設定は、Macではうまく機能するのに、Windows WSL2 上では全く動作していない。~~

~~ちなみに、現状はこう。~~

|ローカルマシンOS|接続先リモートサーバOS|動作結果|備考|
|:--|:--|:--|:--|
|Mac|なし (ローカルホスト)|**動いた**|※`Apple M2` で Ruff 利用時は注意が必要！！<br>詳細は「9.」を参照|
|Mac|リモートのUbuntu|**動いた**||
|Windows|WSL2 Ubuntu|**動いた**|厳密にはWSL2はリモートと呼ぶには怪しいが、WSLは仮想マシンということでリモートマシンという扱いにした。|

**WSL でも動作させる方法がわかった**ので、色々と追記した。(2023/10/14)


# 4. 旧設定方法について


ネットで検索すると、大体　`python.formatting.xxx` とか、 `python.linting.xxx` とかの設定を書くように説明されている記事がヒットする。

自分もそれらに従って、以下のような `setting.json` を使っていた。

```json:.vscode/setting.json
{
    "python.formatting.provider": "black",
    "python.formatting.blackPath": "${workspaceFolder}/.venv/bin/black",
    "python.languageServer": "Pylance",
    "python.linting.enabled": true,
    "python.linting.lintOnSave": true,
    "python.linting.mypyEnabled": true,
    "python.linting.mypyArgs": [
        "--ignore-missing-imports",
        "--config-file",
        "pyproject.toml"
    ],
    "python.linting.mypyPath": "${workspaceFolder}/.venv/bin/mypy",
    "python.linting.flake8Enabled": true,
    "python.linting.flake8Path": "${workspaceFolder}/.venv/bin/flake8",
    "python.linting.pylintEnabled": false,
}
```

しかし最近、この設定では以下のような warning が出てしまうようになった。

![スクリーンショット 2023-08-04 9.41.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327407/1b6cac48-bfd0-dde7-1c20-aeadf3ea33d2.png)

> この設定は間もなく非推奨になります。Mypy Type Checker 拡張機能を使用してください。詳細については、「https://aka.ms/AAlgvkb」を参照してください。

これは `"python.linting.mypyPath"` にカーソルを合わせた時の warning だけど、他のも同様に非推奨と言われている。

...いや、実を言うと warning だけではなくて、自分の場合はそもそも `mypy`, `isort`が動かなくなっていた(｡ŏ﹏ŏ)


# 5. 新設定方法

1. VSCodeの拡張を install しましょう！
1. setting.json に書いていた古いlinter設定は消しましょう！
1. **Windwos (WSL) の場合**は、 [8. 各linter設定のカスタマイズ](#8-%E5%90%84linter%E8%A8%AD%E5%AE%9A%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA) が必須


以下で詳しく見ていきます。

## 5-1. VSCodeの拡張を install

![スクリーンショット 2023-08-04 9.55.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327407/1863bcca-8769-e277-bdac-25a7e556bb09.png)

上記画像で示したテキスト入力欄に、 `flake8` や `mypy` と入れると、Microsoft公式の拡張が見つかります。

具体的には以下の4つの拡張を入れました。

|名称|識別子|
|:-|:-|
|Black Formatter|"ms-python.black-formatter"|
|Flake8|"ms-python.flake8"|
|isort|"ms-python.isort"|
|Mypy Type Checker|"ms-python.mypy-type-checker"|

Ruff 使いたい人は以下を入れてね (*´ｖ｀)

|名称|識別子|
|:-|:-|
|Ruff|"charliermarsh.ruff"|

Ruff 使う場合は、`black` とか `isort` はいらないかも。


## 5-2. 古いlinter設定削除

「3. 旧設定方法について」に書かれていたような非推奨設定を全て消せば、最新の設定方法の完了です！(windows (`WSL`) の場合は「5-3.」も必要 )

これで、動かなくなっていた私のlinterも全て復活しました！

※念のためもう一度書きますが、上記のlinter分に関しては、**非推奨になっている古い設定**は全て消しましょう。
消さないと、VSCodeは古い方のlinterを動かそうとします。


## 5-3. WSL の場合

[8. 各linter設定のカスタマイズ](#8-%E5%90%84linter%E8%A8%AD%E5%AE%9A%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA) の作業が必須なようです。

少なくとも私の場合、この設定を行わないと WSL 上の `mypy`、`black`、`isort` については動作しませんでした。( ˘·ω·˘ ).。oஇ


## 5 の補足

:::note info
**linter パッケージの扱いについて**
ここまでの内容を実施すると、 flake8 や mypy を LocalマシンのOS から uninstall しても linter が動くようになります。

VSCode拡張の中に、 linter のコードも含まれているからです。

これにより、`Pipfile` や `requirements.txt` に linter のパッケージを追加する必要はなくなります。
:::


# 6. lintのエラー確認方法

それでもlinterが動かないときは、以下の画像内の矢印の先にある `{}` マークをクリックすることで、各lintツールのエラー原因を確認できます。

![スクリーンショット 2023-08-04 9.48.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327407/7c9262a9-5aef-24bd-f8cb-b9dff828459f.png)

ここでログを確認できるのは、おそらくVSCode拡張をインストールした分だけだと思います。


# 7. isort設定の補足

ちなみに、 `isort` の以下の設定については、非推奨にはならなかったのだけど、

```json
{
    "isort.path": [
        "${workspaceFolder}",
        ".venv",
        "bin",
        "isort"
    ],
}
```

私の環境でこれを設定すると、
なぜか「対象ディレクトリにアクセスする権限がない」(`PermissionError: [Errno 13] Permission denied:`)という以下のようなエラー

```bash
2023-08-04 10:02:34.570 [info] Error while detecting isort version:
Traceback (most recent call last):
  File "/Users/user_name/.vscode/extensions/ms-python.isort-2023.10.1/bundled/tool/lsp_server.py", line 419, in _log_version_info
    result = _run_tool(["--version-number"], settings)
  File "/Users/user_name/.vscode/extensions/ms-python.isort-2023.10.1/bundled/tool/lsp_server.py", line 690, in _run_tool
    result = utils.run_path(argv=argv, use_stdin=True, cwd=cwd)
  File "/Users/user_name/.vscode/extensions/ms-python.isort-2023.10.1/bundled/tool/lsp_utils.py", line 157, in run_path
    with subprocess.Popen(
  File "/Users/user_name/.pyenv/versions/3.10.11/lib/python3.10/subprocess.py", line 971, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/Users/user_name/.pyenv/versions/3.10.11/lib/python3.10/subprocess.py", line 1863, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
PermissionError: [Errno 13] Permission denied: '/Users/user_name/src/repository_root'
```

が出て、isortが効かなくなっていました。
そのため、私はこの設定も消しました。
そしたらなぜか `isort` が動きました。

`"isort.path"` も非推奨でいいんじゃないかな...？( ˘·ω·˘ ).。oஇ


# 8. 各linter設定のカスタマイズ

Windows (WSL) の場合は、以下の設定が必須っぽいです。

## 8-1. flake8

`flake8`に関しては、こんなふうに書いたら、設定が効いた。

```json:settings.json
{
    "flake8.args": [
        "--max-line-length=100",
        "--max-complexity=10",
        "--config=<file_path>"
    ],
}
```

`--config=`は試してないけど、 VSCode の公式 document に載っていた事例なので、おそらく効くだろう。

flake8設定に関する公式 document のリンクも以下に貼っておきます。

https://marketplace.visualstudio.com/items?itemName=ms-python.flake8


## 8-2. mypy

mypyはこう。

```json:settings.json
{
    "mypy-type-checker.args": [
        "--ignore-missing-imports",
        "--disallow-untyped-defs",
        "--config-file=<file>"
    ]
}
```

`--config-file`のところは、各自自分の設定ファイルを書いてね（試してない）。

mypy設定に関する公式 document のリンクは以下の通り。

https://marketplace.visualstudio.com/items?itemName=ms-python.mypy-type-checker


## 8-3. black

とりあえず、black の最低限の設定。

```json:setting.json
{
    "[python]": {
        "editor.defaultFormatter": "ms-python.black-formatter",
        "editor.formatOnSave": true
    }
}
```

black の設定に関する公式 document のリンクは以下の通り。

https://marketplace.visualstudio.com/items?itemName=ms-python.black-formatter


## 8-4. isort

isort の設定だよ。

```json:setting.json
{
    "[python]": {
        "editor.defaultFormatter": "ms-python.black-formatter",
        "editor.formatOnSave": true,
        "editor.codeActionsOnSave": {
            "source.organizeImports": true
        },
    },
    "isort.args":["--profile", "black"],
}
```

isort の設定に関する公式 document のリンクは以下の通り。

https://marketplace.visualstudio.com/items?itemName=ms-python.isort


## 8-5. 完成形 (windows 用 flake8, mypy, black, isort 対応)

これで、windows でも flake8、mypy、black、isort が動くようになる。

```json:settings.json
{
    "[python]": {
        "editor.defaultFormatter": "ms-python.black-formatter",
        "editor.formatOnSave": true,
        "editor.codeActionsOnSave": {
            "source.organizeImports": true
        },
    },
    "isort.args":["--profile", "black"],
    "flake8.args": [
        "--max-line-length=100",
        "--max-complexity=10",
    ],
    "mypy-type-checker.args": [
    ],
}
```


`"--config=<file_path>"` や `"--config-file=<file>"` は別に要らない。
mypy に関しては、設定項目が上記のような空配列であっても動作することが確認できた。


# 9. Ruffについて (_new!!_)

Ruff の設定方法を追記しました。
black や isort (、flake8 とも？) などと機能が重複しているので、別枠にしてあります。

## 9-1. Mac の場合の注意事項

Mac OSの場合 `error: Ruff crashed.` といったエラーが発生する場合がある。
発生した環境は以下の通り。

||バージョンなど|
|:-|:-|
|OS|macOS Ventura 13.6（22G120）|
|CPU|Apple M2|

この場合、OSに `Rust` をインストール必要がある気がする...よくわかってない(未対応)

関連があると思われる GitHub issue を載せておく。

https://github.com/astral-sh/ruff-vscode/issues/362

自分の場合は、いつの間にかこのエラーが解消してしまっていて、エラーも再現できないので、対策を明示できません。(申し訳ない...)
もし何かわかればコメントいただけるとありがたいです。


## 9-2. install する extension

もう1回書いておくね。
これだよ。

|名称|識別子|
|:-|:-|
|Ruff|"charliermarsh.ruff"|

## 9-3. settings.json の設定

以下のように書いてね。
この設定で ruff が動いたよ ( \*˙︶˙*\)و

### ※ 2024/03/11 追記: 要注意

- `"source.fixAll.ruff"`, `"source.organizeImports.ruff"` が `true` じゃなくて、 `"explicit"` になったかも。余裕がなくて調べられてないけど、後で調べて更新したい。


```json:settings.json
{
    "[python]": {
        "editor.codeActionsOnSave": {
            "source.fixAll.ruff": true,
            "source.organizeImports.ruff": true
        },
        "editor.formatOnSave": true,
    }
}
```

windows でも Mac でも、設定に関しては少なくともこれで動きました。

Ruff の設定方法詳細は、以下の公式ドキュメントに書かれているよ。

https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff

https://github.com/astral-sh/ruff-vscode#usage

（上記2つのサイトは、どちらもほぼ同じことが書かれている。）


## 9-4. Ruff の機能について

以下のサイトに結構詳しいことが書かれているよ。

https://docs.astral.sh/ruff/faq/


## 9-5. Ruff について感じていること

Ruff は、 flake8 の何十倍も速いと言われているし、 isort[^1]、black[^2]、flake8[^3] の機能は大体カバーしている模様。なので、この3つはもう置き換えてもいい気がする。

ただ、mypy の機能まではカバーしてない[^4]みたい( ˘ω˘)
mypy 結構好きなので、mypy はこれまで通り使うつもり。

[^1]: [isort と ruff の互換性について](https://docs.astral.sh/ruff/faq/#how-does-ruffs-import-sorting-compare-to-isort)
[^2]: [black と ruff の互換性について](https://docs.astral.sh/ruff/faq/#how-does-ruffs-formatter-compare-to-black)

[^3]: [flake8 と ruff の互換性について](https://docs.astral.sh/ruff/faq/#how-does-ruffs-linter-compare-to-flake8)

[^4]: [mypy と ruff の互換性について](https://docs.astral.sh/ruff/faq/#how-does-ruff-compare-to-mypy-or-pyright-or-pyre) （互換ではないので、mypy は Ruff とセットで使うのがオススメ）