Python debugging in Sublime Text & Docker


dockerdocker-composedjangopythondebuggersublime text

Obwohl ich den Python Debugger gerne verwende blickte ich oft etwas neidisch auf meine Kollegen mit ihrer PyCharm IDE und dem integrierten visuellen Debugger. Manchmal ist es einfach praktisch alle Variablen direkt zu sehen, Haltepunkte über den Editor zu setzen oder auch die (Django-)Templates bequem zu debuggen.

Nach einigen Versuchen u.a. auch mit pudb unternahm ich vor ein paar Tagen einen neuen Versuch. Über Visual Studio Code kam ich auf die Idee das Debug Adapter Protocol etwas näher zu untersuchen nachdem ich auf den Artikel Debug django with docker and vs code von Emily Morehouse gestoßen war.

Integration

Auch wenn dieser Artikel etwas länger geworden ist als gedacht, sollten erfahrene Programmierer diesen Guide in ein paar Minuten bereits testen können.

Django Projekt

Die debugpy-Integration in ein bestehendes Django Projekt war einfach, lediglich das debugpy Package wollte über pip bzw. requirements.txt installiert werden und die manage.py angepasst.

Aus Bequemlichkeit habe ich noch die ENV-Variablen DEBUGPY_PORT und DEBUGPY_ENABLED eingeführt, letztere um zu verhindern, dass der Server in Production mit aktiviert wird.

Aktuell sieht damit meine manage.py Datei wie folgt aus:

#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys


def main():
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings')
    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line(sys.argv)


def debugger():

    import debugpy
    debugpy_port = int(os.environ.get('DEBUGPY_PORT', 4711))

    try:
        debugpy.listen(('0.0.0.0', debugpy_port))
        print(f'Started debugpy at port {debugpy_port}.')
    except RuntimeError:
        print(f'Debugpy port {debugpy_port} already in use.')


if __name__ == '__main__':

    if os.environ.get('RUN_MAIN') and os.environ.get('DEBUGPY_ENABLED', False):
        debugger()

    main()

Sublime

Die Einrichtung in Sublime war auch sehr übersichtlich:

  1. Debugger Package installieren
  2. Projekteinstellungen anpassen

demo.sublime-project

{
    "folders":
    [
        {
            "name": "Projektname",
            "path": "/path/to/project",
        },
    ],
    "debugger_configurations": [{
        "name": "[django:docker] runserver",
        "type": "python",
        "request": "attach",
        "pathMappings": [{
            "localRoot": "/path/to/project",
            "remoteRoot": "/application"
        }],
        "port": 4711,
        "host": "localhost",
        "debugOptions": [
            "Django"
        ],
        "autoReload": {
            "enable": true
        }
    }],
}

Tipp: Als brauchbarer Shortcut für macOS hat sich bei mir ^ ESC erwiesen, unter Tastatur -> Kurzbefehle auf “Open” gelegt.

Docker

Zu guter Letzt, muss nur noch der gewählte Port im Docker Service freigegeben werden. Ein idealer Fall für die lokale docker-compose.override.yml!

Erweiterung für override

django:
    ports:
        - 4711:4711

Vollständiger Service

django:
    build:
        context: .
        args:
            - APPLICATION_NAME=${APPLICATION_NAME}
            - APPLICATION_USER=${APPLICATION_USER}
    command: python source/manage.py runserver 0.0.0.0:8000
    volumes:
        - .:/application
    restart: "no"
    ports:
        - 4711:4711

Visual Studio Code

Der Vollständigkeit halber auch ein .vscode/launch.json Beispiel

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "[django:docker] runserver",
            "type": "python",
            "request": "attach",
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}",
                    "remoteRoot": "/application"
                }
            ],
            "port": 4711,
            "host": "localhost",
            "justMyCode": false
        }
    ]
}

Ergebnis

Debugging Django Pug Template with debugpy

Quellen

Meta-level


Article language
German
Article date
Sept. 29, 2021
Updated at
Oct. 2, 2021