1. Install `ptvsd` using the same Python interpreter Qgis uses. E.g. on Windows: ``` C:\OSGeo4W64\apps\Python37\python.exe -m pip install ptvsd==4.3.2 ``` 2. Add a debug configuration to `launch.json`: ``` { "name": "Python: Remote Attach", "type": "python", "request": "attach", "port": 5678, "host": "localhost", "pathMappings": [ { "localRoot": "${workspaceFolder}", "remoteRoot": "${workspaceFolder}" } ] } ``` 3. Add code that attaches the debugger when your plugin launches: ``` import sys import traceback from qgis.core import QgsMessageLog, Qgis MESSAGE_CATEGORY = 'Messages' def enable_remote_debugging(): try: import ptvsd if ptvsd.is_attached(): QgsMessageLog.logMessage("Remote Debug for Visual Studio is already active", MESSAGE_CATEGORY, Qgis.Info) return ptvsd.enable_attach(address=('localhost', 5678)) QgsMessageLog.logMessage("Attached remote Debug for Visual Studio", MESSAGE_CATEGORY, Qgis.Info) except Exception as e: exc_type, exc_value, exc_traceback = sys.exc_info() format_exception = traceback.format_exception(exc_type, exc_value, exc_traceback) QgsMessageLog.logMessage(str(e), MESSAGE_CATEGORY, Qgis.Critical) QgsMessageLog.logMessage(repr(format_exception[0]), MESSAGE_CATEGORY, Qgis.Critical) QgsMessageLog.logMessage(repr(format_exception[1]), MESSAGE_CATEGORY, Qgis.Critical) QgsMessageLog.logMessage(repr(format_exception[2]), MESSAGE_CATEGORY, Qgis.Critical) class MyQgisPlugin: def __init__(self, iface): enable_remote_debugging() # ... the rest of your plugin code ``` 4. In VS Code start debugging using the Python: Remote Attach configuration defined above ## Debugging tasks / multithreading In order to line-by-line debug code started in another thread, e.g. when running a QTask, add `ptvsd.debug_this_thread()` after the thread split. E.g. in the `run()` function of your task (here from a function): ``` def run(task): import ptvsd ptvsd.debug_this_thread() ``` ## Acknowledgement This gist is based on one written by [AsgerPeterson](https://gist.github.com/AsgerPetersen/9ea79ae4139f4977c31dd6ede2297f90). Instead of installing a third-party Qgis plugin for attaching the debugger, I added the code in point 3.