背景
これまで開発する際、これまでは print() 文を使ってデバッグしていることがほとんどでした。
しかし、ついうっかりコミットログに print文を残してしまうなど、保守性や安全性の面で課題がありました。
そこで、より安全でスマートにデバッグできる VSCodeのデバッグツール を導入することにしました。
VSCodeにはGUIでデバッグできる機能が備わっていますが、実行ディレクトリやモジュールパスの関係でエラーになることも多くあります。なのでCLIでターミナルからデバッグできるように実装しました。
内容
- ターミナル(CLI)からPythonを実行し、VSCodeからアタッチしてデバッグする方法の紹介
- 冗長なデバッグコマンドを短縮する方法の紹介
方法
debugpyをインストール
pip install debugpy
.vscodeにてlaunch.jsonにて以下を記述
(localRootは実行するディレクトリに合わせて設定してください。 筆者はここで詰まりました。)
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach to Debugpy",
"type": "debugpy",
"request": "attach",
"connect": {
"host": "localhost",
"port": 5678
},
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "."
}
]
}
]
}
実行コマンド
python -m debugpy --listen 5678 --wait-for-client src/service/item.py
これでwaiting for client...と表示され、vscodeからアタッチ可能な状態になります。
vscodeで接続
- デバッグしたい行にブレークポイントを置く
- cmd+shift+Dでデバッグタブを開く
- [Attatch to Debugpy] を選択して実行
これでブレークポイントで停止し、変数の中身をGUIで確認出来ます。
工夫ポイント
上記のコマンドは長く、オプションも多いです。
そのため、MakefileやPythonのコマンド実行ライブラリ(invoke等)を活用してコマンドを短縮すると便利です。
Makefileの場合
# MacOS/Linux用
PYTHON = python
DEBUG_PORT = 5678
debug:
$(PYTHON) -m debugpy --listen $(DEBUG_PORT) --wait-for-client $(file)
実行方法
make debug file=src/service/item.py
#MacOSでのみ動作確認済み。
import os
from invoke.tasks import task
@task
def debug(c, filename):
path = os.path.abspath(os.path.dirname(__file__))
if os.name == "nt":
c.run(
f'set "pythonpath=%PATH%;{path}" && python -m debugpy --listen 5678 --wait-for-client {filename}'
)
else:
c.run(
f'export PYTHONPATH="$PYTHONPATH:{path}" && python -m debugpy --listen 5678 --wait-for-client {filename}'
)
実行方法
inv debug src/service/item.py
まとめ
debugpy を使うことで、コードにprint文を残さず安全にデバッグすることが可能になりました。
また、Makefileやinvokeでコマンドを抽象化すれば、毎回長いオプションを覚えるが必要なくなります。