VSCodeのPython開発環境でpylintの代わりにflake8を導入し自動整形を設定する

## flake8とは？

flake8はpythonの以下の3つのエラーチェックをしてくれるモジュールのラッパーです。

* pep8：コードスタイルがPEP8に準拠しているかをチェック
* pyflakes：コードの論理的エラーをチェック（スタイルのチェックは除く）
* mccabe：コードの循環的複雑度のチェック（分岐やループを定義式で数値化するみたいです）

要はお勧めのエラーチェックの抱き合わせで、これを入れておけば安心・・・みたいに思っておけばいいのかもしれません・・・（汗

因みにパッケージモジュールのpep8は、最近pycodestyleという名前に変わったらしいので、flake8をインストールするとpep8の代わりにpycodestyleが関連モジュールとしてインストールされます。

### VSCodeへの導入方法は？

結論から書くと、VSCode上のコードをflake8によりエラーチェックと書式整形を適用するには、VSCodeのSettingsで次の設定を行い、pythonの実行環境（または仮想環境）に必要なモジュールをインストールすることで実現できます。

---

### VSCodeのSettings

設定名                         |機能                            |設定値
---|:--|:--
python.linting.enabled        |Lint機能を有効にするかどうか        |true
python.linting.pylintEnabled  |Linterにpylintを使用するかどうか  |false
python.linting.flake8Enabled  |Linterにflake8を使用するかどうか  |true
python.linting.lintOnSave            |ファイル保存時にLintを実行するか   |true
python.formatting.provider    |Pythonコードの整形に何を使用するか |autopep8
editor.formatOnSave           |ファイル保存時に自動整形するかどうか| true

### インストールモジュール

次のコマンドにより、必要なモジュールをインストールします。

```shell
pip install flake8
pip install autopep8
```

---

それでは、導入手順を具体的に記載してゆきます。

## pylintを無効化する

VSCodeではpylintがデフォルトで有効になっているので、まずは無効化します。

まず、VSCodeの左下のギアアイコンからメニューを開き、設定をクリックしてSettingsを開きます。（VSCode1.28.xからは、settings.jsonファイルを直接編集する仕様から変わったようです）

![settings.png](https://qiita-image-store.s3.amazonaws.com/0/299676/3f52ffff-5d55-aaba-a708-f7ed5371749e.png)

検索バーにpython.linting.pylintEnabledを入力してフィルタリングするとPylintのEnabled設定が表示されるので、図のようにチェックをはずします。

![pylintenabled.png](https://qiita-image-store.s3.amazonaws.com/0/299676/6de3a119-a9d3-3abb-daea-cfed5bf28d7c.png)

因みに、チェックを外すことで、settings.jsonの以下と同義となります。

```text
"python.linting.pylintEnabled": false
```

設定後、表示されているトースト通知を閉じると、以降は表示されなくなります。

ついでにpythonのlintingを有効化("python.linting.enabled": true)します（デフォルトでtrueになっている場合は変更の必要はありません）。

![linting.enabled.png](https://qiita-image-store.s3.amazonaws.com/0/299676/6e64358f-1b60-ee2a-ee98-a7201f3f7a65.png)

## flake8を導入する

python.linting.flake8Enabledを検索して、有効化(true)します。

![flake8Enabled.png](https://qiita-image-store.s3.amazonaws.com/0/299676/91c4a82e-b04b-f00a-5a4d-07fa18e6369b.png)

```text
"python.linting.flake8Enabled": true
```

変更するとトースト通知で「flake8がないよ」というメッセージが英語で表示さるので、そのままInstallするか、環境下で次のコマンドによりpep8をインストールします。

```shell
pip install flake8
```

## ファイル保存時にlintingをチェックする設定にする

検索バーにpython.linting.lintOnSaveをフィルタリング表示し有効化することで、ファイルの保存時にエラーチェックが働きます。

![lintonsave.png](https://qiita-image-store.s3.amazonaws.com/0/299676/1576dd7d-46e3-9371-b7eb-12045aac07fd.png)

```text
"python.linting.lintOnSave": true
```

## 自動整形するフォーマットを設定する

右クリックメニューの
pep8(pycodestyle)で自動整形するよう設定します。

### 自動整形のフォーマットをpep8に指定する

PEP8に準拠した自動整形を、検索バーによりpython.formatting.providerを探しautopep8を選ぶことで、自動整形するフォーマットをpep8に指定します。
（flake8によるコードスタイルはpep8（厳密にはpycodestyle）なので、pep8に準拠した整形を行うモジュールautopep8をフォーマッタとして指定します。）

![provider-autopep8.png](https://qiita-image-store.s3.amazonaws.com/0/299676/4c1e67ef-2386-9cbc-50a8-967829151c68.png)

```text
"python.formatting.provider": autopep8
```

設定と同時に、Python環境にもautopep8をインストールします。

```shell
pip install autopep8

# Collecting autopep8
# Collecting pycodestyle>=2.4.0 (from autopep8)
#   Using cached https://files.pythonhosted.org/packages/e5/c6/ce130213489969aa58610042dff1d908c25c731c9575af6935c2dfad03aa/pycodestyle-2.4.0-py2.py3-none-any.whl
# flake8 3.5.0 has requirement pycodestyle<2.4.0,>=2.0.0, but you'll have pycodestyle 2.4.0 which is incompatible.
# Installing collected packages: pycodestyle, autopep8
#   Found existing installation: pycodestyle 2.3.1
#     Uninstalling pycodestyle-2.3.1:
#       Successfully uninstalled pycodestyle-2.3.1
# Successfully installed autopep8-1.4.2 pycodestyle-2.4.0
```

>autopep8はフォーマットの参照先として、関連モジュールとしてインストールされるpycodestyleを参照します。

右クリックメニューの「ドキュメントのファーマット」を選択することでpep8(pycodestyle)で自動整形できます。

![document_format.png](https://qiita-image-store.s3.amazonaws.com/0/299676/19bcd709-a744-bba9-034e-c9354df7acb4.png)

### 保存時に自動整形する設定にする

検索バーよりeditor.formatOnSaveを探し有効(true)にすることで、自動整形されるよう設定します。

![formatonsave.png](https://qiita-image-store.s3.amazonaws.com/0/299676/a142f7be-c8e0-89b6-0469-3f91aa4d4f02.png)

```text
"editor.formatOnSave" : true
```

以上により、ファイルを保存すると自動整形が行われます。

うまく自動整形が行われない場合、（flake8とautopep8）それぞれのモジュールが必要とするpycodestyleのバージョンが異なると、lintや自動整形がうまくいかない場合があります。その場合は、依存関係をチェックするモジュールpipdeptreeでパッケージの依存関係を調べることによりバージョンのコンフリクトも調べられるので、どちらの条件も満たすpycodestyleのバージョンに変更するか、どちらも満たせない場合は優先する機能に合わせて、pycodestyleのバージョンを変更してください。

```shell
pip install pipdeptree
```

インストールしたpipdeptreモジュールを実行してパッケージの依存関係を調べると、autopep8が必要とするpycodestyleのバージョンが2.4.0以上なのに対し、インストールされているバージョンが2.3.1なので、整合性がとれません。

```shell
pipdeptree

# autopep8==1.4.2
#   - pycodestyle [required: >=2.4.0, installed: 2.3.1]
# flake8==3.5.0
#  - mccabe [required: >=0.6.0,<0.7.0, installed: 0.6.1]
#  - pycodestyle [required: >=2.0.0,<2.4.0, installed: 2.3.1]
#  - pyflakes [required: >=1.5.0,<1.7.0, installed: 1.6.0]
```

調べてみると、flake8が3.6.0にアップデートされていましたので、最新バージョンにアップデートを試みます。

```shell
pip install flake8 -U
```

改めてバージョンと依存関係を確認すると、flake8のバージョンが3.6.0にアップデートされたことに合わせてpycodestyleのバージョンも2.4.0以上にアップデートされ、autopep8と整合性がとれました。

```shell
pipdeptree

# autopep8==1.4.2
#   - pycodestyle [required: >=2.4.0, installed: 2.4.0]
# flake8==3.6.0
#   - mccabe [required: >=0.6.0,<0.7.0, installed: 0.6.1]
#   - pycodestyle [required: >=2.4.0,<2.5.0, installed: 2.4.0]
#   - pyflakes [required: >=2.0.0,<2.1.0, installed: 2.0.0]
#   - setuptools [required: >=30, installed: 40.4.3]
# pipdeptree==0.13.1
#   - pip [required: >=6.0.0, installed: 18.1]
# wheel==0.32.1
```

最新版のflake8をインストールしても、autopep8の要求pycodestyleと整合性がとれない場合は、暫くしてからflake8またはautopep8の最新版が更新されるまで待ってからアップデートするとよいかもしれません。

モジュールのインストール時にpycodestyleの整合性が取れない場合や、PEP8を覚えようとする場合は敢えて保存時の自動整形の機能を切り、PEP8が分かって来た頃に改めてpycodestyleの整合性を整え、自動整形をONにして効率化を図るのも一つ方法でしょう・・・。

## flake8のエラーチェックでpycodestyle(pep8)の1行文字数制限を外す

標準コーディング規約PEP8の一行あたりの文字数制限は79文字のため、制限が少し厳しいです。（本来はあまりよろしくないのかもしれませんが）80文字以上でエラーが出るのは流石に避けたいのでこのエラーチェックを外します。

具体的には、ラッパーであるflake8の実行時の引数に、エラー（E501 line too long）を無視する値を指定します。

Settingsの検索バーにflake8argsを入力して項目をフィルタリングし、項目の「settings.jsonで編集」をクリックして開きます。

![settings_flake8args.png](https://qiita-image-store.s3.amazonaws.com/0/299676/dc4dc325-6b4d-2f51-2afc-fa18cf849313.png)

開かれたsettings.jsonのpython.linting.flake8Argsにマウスカーソルを合わせると左端にペンの様な編集アイコンが表示されるのでクリックし、表示される「設定にコピー」によりユーザー設定に項目をコピーし、コピーされたpython.linting.flake8Argsのカッコ内に"--ignore=E501"を入力して保存します。

![settings_flake8args.json.png](https://qiita-image-store.s3.amazonaws.com/0/299676/e6aa33e2-f893-2d97-dc02-963ae684f9bd.png)

以上で、文字数制限のエラーチェックを外せるはずです。
## 参考にしたサイト

* [https://blog-ja.sideci.com/entry/python-lint-pickup-5tools](https://blog-ja.sideci.com/entry/python-lint-pickup-5tools)

* [http://www.atmarkit.co.jp/ait/articles/1711/24/news034_3.html](http://www.atmarkit.co.jp/ait/articles/1711/24/news034_3.html)