カタベログ

IT技術に関するブログを書きたい.食べ物関連はInstagramをご参照の事.

ぼくのかんがえたさいきょうのVSCodeでのPython開発環境

序文

Pythonを初めて触ったのは筆者が19歳のとき……プログラミングに目覚め始めた頃、そのときに出会ったRubistの方への反骨精神で使い始めました。 あれから月日が流れ、結婚、出産、育児、マイホーム・マイカー購入といった人生一大イベントたちをことごとく無視して生きてきて、遂にお仕事でPythonを本格的に使う日が来ました(やったー)。

筆者はWebアプリケーションエンジニアとしてはJavaScript/TypeScriptの経験が長いです(といっても2、3年ですが)。 その中でリンターやフォーマッターといった自動でいい感じのコードを書くための技術に触れ、それらのVSCodeでの設定の方法を学んできました。 そして今回Pythonを扱うとなって調べてみると、Pythonもその手のツールは当然のように存在しております。 そうなると、VSCodeに慣れ親しんだ筆者としては「VSCodeでJS/TSを書いていた時のような感覚でPythonを書きたい」と思うのが極めて自然ですよね。

ということで、自分がVSCodeに設定しているPython関連の設定内容と推奨拡張を記載しつつ、途中ちょっとハマったところもあったのでその事例を共有できたらなって思います。

なお、PyCharm使えばいいじゃんとかそういう意見は求めてません。悪しからず。

目次

設定

VSCodeなのでプロジェクトルートに.vscodeを作成し、その中にsettings.jsonを作成してそこに設定を記載します。 今回採用するツールは以下であり、venv環境はOS依存性を排除できると思ってプロジェクトルートに存在するようにあらかじめ設定しています。

  1. black(フォーマッタ)
    1. 最強フォーマッタっぽいんで採用
  2. isort(フォーマッタ)
    1. 綺麗にimport文並んでくれているのが気持ちがいいので採用
  3. autoflake(リンター)
    1. ただのflake8よりautoの方が自動でいろいろやってくれやすそうなので採用
  4. Pylance(静的解析(型チェック))※VSCode拡張で提供される専用ツール
    1. Microsoftさん肝入りの機能なので採用
  5. mypy(静的解析(型チェック))
    1. もしかしたらそうしてもPyCharm使いたい!って人がいるかもと思って採用
  6. bandit(静的解析(脆弱性分析))
    1. 脆弱なコードは書きたくないよねってことで採用
  7. pytest(テスティングフレームワーク
    1. unittestやdoctestよりも高度なテストが可能で拡張性もあるデファクトスタンダードのものなので採用
{
  "[python]": {
    "editor.codeActionsOnSave": {
      "source.organizeImports": true
    },
    "editor.formatOnSave": true,
    "editor.rulers": [88]
  },
  "isort.path": ["${workspaceFolder}/.venv/bin/isort"],
  "python.analysis.inlayHints.functionReturnTypes": true,
  "python.analysis.inlayHints.variableTypes": true,
  "python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python",
  "python.formatting.provider": "black",
  "python.formatting.blackPath": "${workspaceFolder}/.venv/bin/black",
  "python.languageServer": "Pylance",
  "python.linting.banditEnabled": true,
  "python.linting.banditPath": "${workspaceFolder}/.venv/bin/bandit",
  "python.linting.banditArgs": [
    "--configfile",
    "${workspaceFolder}/bandit.yaml"
  ],
  "python.linting.enabled": true,
  "python.linting.flake8Enabled": true,
  "python.linting.flake8Path": "${workspaceFolder}/.venv/bin/autoflake",
  "python.linting.lintOnSave": true,
  "python.linting.mypyEnabled": true,
  "python.linting.mypyPath": "${workspaceFolder}/.venv/bin/mypy",
  "python.linting.pylintEnabled": false,
  "python.testing.pytestEnabled": true,
  "python.testing.pytestPath": "${workspaceFolder}/.venv/bin/pytest",
  "python.terminal.activateEnvInCurrentTerminal": true,
}

あくまで設定ファイルなので、機能のOFF/ONやツール名の選択とパスの設定が主です。

ハマったところ

ここまで設定しても自分だけフォーマッタが動かない

原因は簡単で、VSCodeのユーザ設定と衝突していたからでした。 気づけたのは、新規でセットアップした人は動くけど自分だけが動かないと分かったからでした。

Editor: Default Formatterという設定がユーザ設定にもあるのですが、ここがなし(Null)じゃないと、フォーマッタ設定がぶつかり合って結果動作しないってことが起こり得ます。 ワークスペース設定がオーバライドすると思い込んでいたのですが、どうやら必ずしもそうじゃないこともあるみたいです。VSCode難しい!

推奨拡張

続いては推奨拡張です。 メジャーなものを入れてますが、設定にも登場したPylanceを動作させるにはpipインストールではなく拡張のインストールなのでとても大事です。

{
  "recommendations": [
    "ms-python.python",
    "ms-python.vscode-pylance",
    "kevinrose.vsc-python-indent",
    "njpwerner.autodocstring",
    "donjayamanne.python-environment-manager"
  ]
}

ハマったところ

Windows開発環境で拡張が読み込まれない

原因は開発の都合でWSL2側に拡張が入っていないからでした。

mac OSWindowsが混在する状態での開発だと、都合Windowsネイティブでの開発はつらいのでWSL2を使ってもらうようにしてました。 VSCodeに限らずだとは思いますが、WSL2は仮想環境の一種なので、Windowsと設定が分離しておりWindows側で拡張を入れてもWSL2から起動した場合は拡張が動かないということが起きます。 同じような話で、WSL2でPythonのvenv環境を構築してもWindows側ではうまく扱えないので、先の設定でキメキメに設定したリンター・フォーマッターも大抵動かなくなります。 開発端末のOSを統一できればいいのでしょうが、選択の自由もあるのでそうはいかないのが世の常です。OSが混在、特にWSL2のような仮想環境が絡む場合は気をつけていただきたいです。

WSL2とかWindowsを否定したい意図はないので悪しからず。

その他

デバッガ設定

今回は今をときめく?FastAPIを用いて実装しています。

こちらのドキュメントを参考に、APIサーバエントリーポイント(大抵の人はmain.pyってファイルで実装しているかな?)に加筆し、 .vscode/launch.jsonというファイルを用意することでデバッガをアタッチした状態でAPIサーバを動かすことができます。 開発してて結構便利で、どうしてもテストコードだけではわからないバグを見つけられたり、リモートサーバ上では難しい再現検証と内部状態の確認がしやすくなってバグ修正が楽になるので設定しておくことをお勧めします

以下が自分が用意している.vscode/launch.jsonの内容です。

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Python: FastAPI",
      "type": "python",
      "request": "launch",
      "program": "src/main.py",
      "console": "integratedTerminal",
      "autoReload": { "enable": true },
      "env": { "PYTHONPATH": "${workspaceRoot}" },
      "envFile": "${workspaceFolder}/.env",
      "stopOnEntry": false
    }
  ]
}

VSCodeの設定適用の優先順位?

今回のプロジェクトではエセモノレポでやっており、ワークスペースにはJS/TSやJSONMarkdownなど色々入っています。 筆者は冒頭に述べたようにJS/TSをメインで扱っていたので、Prettierの設定がユーザ設定に入っていたことで色々問題も起きました……。

そんな問題らを解決している中で、JS/TSファイルとJSONファイルのフォーマッターを当てるにあたって、editor.formatOnSaveを片方ではfalse、片方ではtrueにしたいというニーズが出てきました。 「いやーこれは無理だなー」って匙を投げる直前、言語固有設定の記載順番を入れ替えると上手くいくことに気づきました。 以下のようにすることで、期待した通りに全てパターンで保存時にフォーマッタがかかるようになったのです。

いまいち原理がわからないのですが、推測として以下をしています。 眉唾なので、本当に困った時に最終手段でやってみる程度のレベルで参考にしてください。

  1. 行番号が若い順から適用チェックが入る?
  2. JSが書いてあるとJSONファイルでもJSの設定を踏襲する(逆も然り)っぽい?
  3. JSとJSONを別に別に書いてあってもJSONが先に書かれているとそれが優先になるっぽい?
 "[javascript]": {
    "editor.codeActionsOnSave": {
      "source.fixAll.eslint": true
    },
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.formatOnSave": false
  },
  "[typescript]": {
    "editor.codeActionsOnSave": {
      "source.fixAll.eslint": true
    },
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.formatOnSave": false
  },
  "[json]": {
    "editor.codeActionsOnSave": {
      "source.fixAll.eslint": true
    },
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.formatOnSave": true
  },