Open4

VSCode と pysen を併用する際の設定メモ

Yuta OkamotoYuta Okamoto

VSCode がファイルの保存時に自動整形してくれる機能を、pysen と互換性がある形で使えるようにしたかったので色々と試したメモ。VSCode で整形したソースが、CI 上の pysen run lint でそのまま通る状態を目指す。

準備

公式の README に沿って設定した後に、pysen generate コマンドで VSCode に読ませる設定ファイルを export する。

$ pysen generate [out_dir]

コマンドを実行すると、pysen の設定に対応する pyproject.tomlsetup.cfg が書き出されるので、これを適当なディレクトリ(プロジェクトルートとか)に配置する。すでに同名のファイルが存在する場合は、中身をコピペして追記する。

Yuta OkamotoYuta Okamoto

VSCode の設定

ここでは pysen-vscode extension を使わずに、組み込みの isortblackflake8 を使う。

2023年11月22日: VSCode の各種 linter が extension 化した影響で設定の書き方が変わっています。以下は以前の書き方です。最新の書き方については、この記事のコメントを参考にしてください。

先ほど pysen generate で書き出した設定ファイルを VSCode に認識させるため、 .vscode/settings.json に以下の内容を書く。

{
  "python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python",
  "[python]": {
    "editor.formatOnSave": true,
    "editor.defaultFormatter": null, // disable prettier
    "editor.codeActionsOnSave": {
      "source.organizeImports": true
    }
  },
  "python.sortImports.args": [ // isort
    "--settings-path", "${workspaceFolder}/pyproject.toml"
  ],
  "python.formatting.provider": "black",
  "python.formatting.blackArgs": [
    "--config", "${workspaceFolder}/pyproject.toml"
  ],
  "python.linting.enabled": true,
  "python.linting.pylintEnabled": false,
  "python.linting.flake8Enabled": true,
  "python.linting.flake8Args": [
    "--config", "${workspaceFolder}/setup.cfg"
  ],
  "python.linting.mypyEnabled": false,
  "python.linting.lintOnSave": true,
  "python.languageServer": "Pylance",
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "prettier.configPath": ".prettierrc.js"
}

注意点など:

  • 網羅的に書いたので要らない設定があるかも
  • ${workspaceFolder} は文字通りワークスペースのルートを指すので、自分のプロジェクトに合わせて適切にする
  • python.defaultInterpreterPath も自分の開発環境に合わせて適切にする
    • これは UI 上からも設定できる
    • python.pythonPath と書いている記事も散見するが、最新版では非推奨なのでこちらを使う
  • フロントエンドを同じレポジトリに入れているので Prettier の設定がある
    • 不要なら下三行を削ってください
    • これが有効だと Python 側の formatter が動かないので [python] エントリ内で無効化する ("editor.defaultFormatter": null)
  • mypy については未検証。あとで追記するかも
Yuta OkamotoYuta Okamoto

vscode の仕様変更でこの辺の設定の書き方が変わっているようなので、適宜置き換えてください。気が向いたら直すかも。

こういう感じになるはず (未検証):

{
  "python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python",
  "[python]": {
    "editor.formatOnSave": true,
    "editor.defaultFormatter": "ms-python.black-formatter",
    "editor.codeActionsOnSave": {
      "source.organizeImports": true
    }
  },
  "isort.args": [
    "--settings-path", "${workspaceFolder}/pyproject.toml"
  ],
  "black-formatter.args": [
    "--config", "${workspaceFolder}/pyproject.toml"
  ],
  "flake8.args": [
    "--config", "${workspaceFolder}/setup.cfg"
  ],
  ...
}

Python 用の defaultFormatter を明示的に指定するのと、~Enabled は extension 側で有効無効を直接切り替えるようになっており、settings.json には書かないことに注意。

参考:

Yuta OkamotoYuta Okamoto

トラブルシューティング

VSCode で import を自動整形すると pysen run lint で蹴られる

いろいろな原因がありそうだが、僕が遭遇したケースでは、VSCode と pysenisortknown_first_party の認識がズレていたのが原因だった。

Python ファイル内で、known_first_party に含まれるパッケージは import list の一番下に配置されるようになるが、VSCode は、自身のプロジェクト設定に基づいて known_first_party をよろしくしてくれるか何かで、VSCode の外側で pysen lint を実行した場合と異なる結果を正とするようになっていた。

これを防ぐには、pysen に以下の設定を追加する:

[tool.pysen.lint]
...
isort_known_first_party = ["your_package"]

これを pysen generate すると、対応する isort の設定が書き出される:

[tool.isort] # automatically generated by pysen
...
known_first_party = ["your_package"]