QGISをVSCodeでデバッグ実行ができるようになりました。
QGIS側のセットアップ
QGISでまずはdebugvsプラグインをインストールします。
QGISのプラグインリストからdebugvsを選んでインストールします。
ですが、このままだと動作しません。
まずQGISのpython環境にdebugpyをインストールします。
/Applications/QGIS.app/Contents/MacOS/bin/pip3 install debugpy
次に、debugvsに弊社長瀬さんが開発したパッチを当てます。
cd ~/Library/Application\ Support/QGIS/QGIS3/profiles/default/python/plugins/debug_vs curl https://patch-diff.githubusercontent.com/raw/lmotta/debug_vs_plugin/pull/18.patch | patch -p 1
Windowsの方は頑張ってパッチを当ててください。
ここで一旦QGISを落としておきます。
デバッグプラグインの準備
今回はサンプルとして qgis-plugin-qmapcompareを利用します。
では、適当な所にチェックアウトしてからデバッグ実行ができるまで設定しましょう。なお、途中でVSCodeを開いています。
git clone git@github.com:MIERUNE/qgis-plugin-qmapcompare.git cd qgis-plugin-qmapcompare code . cd ~/Library/Application\ Support/QGIS/QGIS3/profiles/default/python/plugins/ ln -s PATH_TO/qgis-plugin-qmapcompare .
次にQGISを起動してプラグインリストを開いてQMapCompareを有効にします。
この後、プラグインのメニューからEnable Debug for Visual Studioメニューからリモートでバッグを可能にします(パッチが当たってないと新しいQGISが起動してしまい、デバッグもできないので必ずパッチを上げてください)。
次にVSCodeを開いて、.vscode/launch.jsonに以下のコードを書きます。
{ "version": "0.2.0", "configurations": [ { "name": "Attach to QGIS", "type": "debugpy", "request": "attach", "connect": { "host": "localhost", "port": 5678 }, "pathMappings": [ { "localRoot": "${workspaceFolder}", "remoteRoot": "${workspaceFolder}", } ], "justMyCode": true } ] }
あとは適当なブレイクポイントを設定してから、VSCodeの実行とデバッグでAttach to QGISを選択します。
今回は起動時の動作を見たかったので QMapCompareの__init__の中にブレイクポイントを仕掛けてから、プラグインリローダーを使ってプラグイン自体のリロードをしてみます。
うまくデバッグができるようになりました。変数にはちゃんとifaceのオブジェクトがなんなのかとかしっかり表示されます。
型がチェックしやすいので型安全なコードも書きやすくなるのではないでしょうか?
ポイントとしてはremoteRootが何故か動かないのでローカルのファイルとpluginsフォルダにあるファイルをSymbolic linkで同期するようにすることです。
なお、これから作るって言う方はいかのように一旦必要なメソッドをpassするようにしたPythonファイルからデバッグしながら作り上げていくとよいでしょう。
from login_dialog import LoginDialog from qgis.gui import QgisInterface from typing import Optional class Lobsta: """QGIS lobsta plugin main class.""" def __init__(self, iface: QgisInterface): self.iface = iface # declare instance attributes self.actions = [] self.menu = "Lobsta" self.toolbar = self.iface.addToolBar("Lobsta") self.toolbar.setObjectName("Lobsta") self.dialog: Optional[LoginDialog] = None def initGui(self): pass def unload(self): pass
ポイントはinitGuiとunloadを最低限実装しているところです。unloadがないとプラグインのリロードで詰まります(unloadが呼び出せないのでリロード時のunload処理が動かない)。
これでQGISの開発もがりがりできますね!