Python Debugging in VS Code - Schneller & Besser Fehlersuchen

Darius Götz .

5. Mai 2026

VS Code: Python-Code mit `Run and Debug` starten. Der `python debugger` ist bereit.

Der Python-Debugger in VS Code spart vor allem dann Zeit, wenn ein Fehler nicht sofort sichtbar ist: Statt blind mit `print` zu arbeiten, halte ich an gezielten Stellen an, prüfe Variablen und gehe den Ablauf Schritt für Schritt durch. In diesem Artikel zeige ich, wie die integrierten Debug-Funktionen praktisch funktionieren, welche `launch.json`-Einstellungen wirklich zählen und wie sich lokale, Test- und Remote-Szenarien sauber voneinander trennen lassen. Wer Python in Visual Studio Code produktiv nutzt, gewinnt damit nicht nur Tempo, sondern auch deutlich bessere Kontrolle über das eigene Programm.

Die wichtigsten Punkte auf einen Blick

  • Für einfache Skripte reicht oft F5; für wiederholbare Setups ist eine eigene launch.json die bessere Wahl.
  • Breakpoints, Conditional Breakpoints und Logpoints decken die meisten Debug-Fälle ohne Umwege ab.
  • launch startet dein Programm direkt, attach verbindet sich mit einem bereits laufenden Prozess.
  • justMyCode: false ist hilfreich, wenn du in die Standardbibliothek hineinsehen willst.
  • Tests, Flask, Django und Remote-Setups funktionieren mit eigenen Profilen deutlich stabiler als mit einem generischen Start.

Warum der Python-Debugger in VS Code im Alltag mehr bringt als `print`

Wenn ich Fehler in Python analysiere, will ich nicht nur sehen, dass etwas schiefgeht, sondern wo sich der Zustand verändert. Genau das leistet der Debugger: Er stoppt die Ausführung an einer definierten Zeile, zeigt mir Variablen im aktuellen Stackframe und erlaubt es mir, den Code kontrolliert weiterlaufen zu lassen. Das ist vor allem bei Schleifen, verschachtelten Funktionsaufrufen, Zustandswechseln und Nebenwirkungen in Datenstrukturen deutlich präziser als eine Kette aus Ausgaben im Terminal.

VS Code bringt dafür die typischen Werkzeuge schon mit: Haltepunkte in der Editorleiste, die Debug-Konsole, Schritt-für-Schritt-Navigation und die Anzeige des aktuellen Aufrufstapels. Für einfache Dateien kann der Editor den aktiven Code oft direkt starten. Sobald ein Projekt aber mehr als ein Einstiegsskript, Umgebungsvariablen oder unterschiedliche Startwege hat, lohnt sich eine feste Konfiguration. Dann ist das Debugging nicht nur bequemer, sondern auch reproduzierbar.

Bevor ich tiefer einsteige, prüfe ich deshalb immer zwei Dinge: den gewählten Interpreter und die Frage, ob ich nur meinen eigenen Code oder auch Bibliothekscode untersuchen will. Damit sind schon viele Fehlstarts vermieden. Als Nächstes geht es deshalb um die saubere Einrichtung, denn dort entscheidet sich, ob Debugging später reibungslos wirkt oder jedes Mal neu zusammengesucht werden muss.

VS Code mit Python-Code und dem

So richte ich eine saubere Debug-Konfiguration ein

Die Grundlage ist fast immer eine launch.json im Ordner .vscode. Ich öffne dafür in VS Code die Run-and-Debug-Ansicht, lege eine Konfiguration an und wähle für Python die passende Debug-Variante. Für ein einzelnes Skript reicht oft program mit ${file}; für ein Projekt mit festem Einstiegspunkt setze ich lieber direkt den Startpfad oder arbeite mit module, wenn das Programm wie bei python -m ... gestartet werden soll.

{
  "name": "Python Debugger: Aktuelle Datei",
  "type": "debugpy",
  "request": "launch",
  "program": "${file}",
  "console": "integratedTerminal"
}
Feld Wofür ich es nutze Praktischer Effekt
request launch oder attach Bestimmt, ob VS Code das Programm startet oder sich an einen laufenden Prozess hängt.
program Pfad zur Einstiegsskript-Datei Gut für feste Startpunkte und reproduzierbare Sessions.
module Start über Modullogik Passend für Aufrufe, die du sonst mit python -m ... startest.
console integratedTerminal oder externalTerminal Steuert, wo Ausgabe und Eingaben landen; das integrierte Terminal ist meist die angenehmste Standardwahl.
cwd Arbeitsverzeichnis Wird wichtig, sobald dein Code relative Pfade zu Dateien verwendet.
args Argumente für dein Programm Hilft bei Startparametern, die du nicht jedes Mal neu eintippen willst.
justMyCode Debugging auf eigenen Code begrenzen false ist nützlich, wenn du in die Standardbibliothek hineinsehen willst.
subProcess Unterprozesse mitdebuggen Sinnvoll bei Workern, Multiprocessing oder Prozessen, die weitere Python-Instanzen starten.

Ich gehe in Projekten oft so vor: erst den richtigen Interpreter auswählen, dann eine schlanke Konfiguration anlegen, dann einen ersten Haltepunkt setzen und mit F5 starten. Für komplexere Fälle ist der Unterschied zwischen launch und attach entscheidend, aber die Grundidee bleibt gleich: Die Konfiguration soll den Startweg dokumentieren, nicht nur den Debugger zum Laufen bringen. Wenn das sauber sitzt, wird die eigentliche Fehlersuche deutlich schneller.

Breakpoints, Logpoints und Bedingungen sinnvoll einsetzen

Ein normaler Breakpoint ist der schnellste Weg, um an einer verdächtigen Zeile anzuhalten. In VS Code setze ich ihn direkt im Rand neben der Zeilennummer. Das reicht in vielen Fällen schon aus. Sobald aber eine Schleife hundertmal läuft oder ein Fehler nur bei einem bestimmten Zustand auftritt, wird ein einfacher Haltepunkt zu grob. Dann kommen bedingte Breakpoints ins Spiel, und genau dort wird Debugging oft erst wirklich effizient.

Typ Wann ich ihn nutze Was er bringt Worauf ich achte
Normaler Breakpoint Bei der ersten unklaren Stelle im Code Stoppt die Ausführung an der markierten Zeile Er ist schnell gesetzt, kann aber bei vielen Durchläufen zu oft stoppen.
Conditional Breakpoint Wenn nur ein bestimmter Fall interessiert Stoppt nur bei einer Bedingung oder nach einer bestimmten Trefferzahl Ideal für Schleifen, Grenzwerte und schwer reproduzierbare Fehler.
Logpoint Wenn ich Informationen brauche, aber nicht anhalten will Schreibt eine Nachricht in die Debug-Konsole Praktisch, wenn ich den Lauf nicht unterbrechen möchte.

Logpoints sind für mich die unterschätzte Zwischenlösung: Ich möchte den Ablauf beobachten, aber nicht bei jedem Durchlauf stoppen. Das spart Zeit, wenn ich zum Beispiel in einer Schleife nur wissen will, wie sich eine Variable entwickelt. Bedingte Breakpoints sind dagegen dann stärker, wenn ich weiß, dass der Fehler nur bei einem bestimmten Wert, einer Trefferzahl oder einem späteren Zustand auftaucht. Ein klassisches Beispiel ist eine Schleife, die erst nach dem fünften oder zwanzigsten Durchlauf kippt.

Für solche Fälle setze ich Bedingungen lieber gezielt als nach Gefühl. Das Debugging wird dadurch weniger laut und deutlich lesbarer. Im nächsten Schritt lohnt sich die Unterscheidung zwischen einem Programmstart aus VS Code und dem Andocken an einen bereits laufenden Prozess, denn genau dort unterscheiden sich viele reale Szenarien.

Launch, Attach und Remote-Debugging sauber trennen

Die wichtigste praktische Trennung ist aus meiner Sicht diese: launch startet das Programm aus VS Code heraus, attach verbindet den Debugger mit einem Prozess, der schon läuft. Für lokale Skripte ist launch meist die einfachere Wahl. Sobald ich aber auf einen Server, einen Container oder einen extern gestarteten Prozess zugreifen will, ist attach die richtige Richtung. Das verhindert, dass ich Startlogik und Debug-Logik unnötig vermische.

Modus Wann ich ihn bevorzuge Stärke Einschränkung
launch Beim normalen Entwickeln auf dem lokalen Rechner VS Code kontrolliert Start, Argumente und Umgebung Der Prozess muss durch die Konfiguration reproduzierbar startbar sein.
attach Wenn das Programm bereits läuft oder extern gestartet wird Gut für Remote-Systeme, Container und Spezialfälle Die Verbindung muss vorher vorbereitet werden, oft mit Port und Pfaden.

Beim Remote-Debugging ist die eigentliche Ursache für Frust oft nicht der Debugger selbst, sondern die Verbindung dazwischen. Typisch ist ein Aufbau mit debugpy.listen(...) und debugpy.wait_for_client() oder ein Start über python -m debugpy --listen ... --wait-for-client. In solchen Setups braucht VS Code zusätzlich eine saubere Pfadzuordnung, also pathMappings, damit lokale Dateien und entfernte Dateien zusammenpassen. Ohne diese Zuordnung stoppt der Debugger vielleicht korrekt, aber die Zuordnung der Zeilen wirkt seltsam oder bricht an der falschen Stelle ab.

Für SSH-Tunnel ist das Prinzip ähnlich: Der entfernte Prozess hört auf einem Port, lokal leite ich denselben Port durch den Tunnel weiter, und VS Code verbindet sich dann auf localhost. Das ist deutlich sicherer als offene Ports und in der Praxis auch besser wartbar. Sobald diese Trennung sitzt, wird die letzte Hürde meist nicht mehr die Verbindung, sondern der spezielle Anwendungsfall selbst.

Tests, Flask und Django profitieren von eigenen Profilen

Ein generisches Debug-Profil reicht bei Tests oder Web-Frameworks oft nur für den ersten Versuch. Danach wird es wertvoll, die Konfiguration auf den Einsatzzweck zuzuschneiden. Für Testläufe kann VS Code direkt einzelne Tests, alle Tests in einer Datei oder den Test an der Cursorposition debuggen. Ich nutze das gern, wenn ein Fehler nur in einem bestimmten Testfall auftritt und ich nicht das ganze Projekt mitlaufen lassen will.

Szenario Typische Konfiguration Warum das hilft
Tests purpose: ["debug-test"] Trennt Test-Debugging sauber vom normalen Programmstart und passt zur Test-Ansicht in VS Code.
Flask module: "flask", env mit FLASK_APP, args: ["run", "--no-debugger"] Entspricht dem echten Startweg der Anwendung und vermeidet falsche Annahmen über den Einstiegspunkt.
Django program: "${workspaceFolder}/manage.py", args: ["runserver"], django: true Aktiviert die für Django relevanten Debug-Funktionen und die Template-Unterstützung.

Ein Detail wird dabei oft übersehen: Testdateien werden beim Debuggen nicht automatisch gespeichert. Ich prüfe also vor dem Start immer, ob der aktuelle Stand wirklich auf der Festplatte liegt. Sonst analysiert man schnell eine alte Version und sucht an der falschen Stelle. Bei Tests kann außerdem justMyCode: false sinnvoll sein, wenn der Fehler tiefer in der Standardbibliothek oder im Laufzeitverhalten sichtbar wird.

Für Web-Apps ist die eigentliche Lehre dieselbe: Nicht jeder Startweg passt zu jedem Projekt. Je näher die Debug-Konfiguration am realen Start liegt, desto weniger Überraschungen gibt es später. Wenn trotzdem etwas nicht stoppt, bleiben meist nur ein paar wiederkehrende Ursachen übrig, die ich als Erstes ausschließe.

Wenn der Debugger nicht stoppt, prüfe ich zuerst diese Fehlerquellen

Die meisten Probleme beim Debuggen sind banal, aber genau deshalb zeitfressend. Ich beginne dann nicht mit der komplizierten Theorie, sondern mit den Basics: Ist die Python-Debugger-Erweiterung installiert und aktiviert? Ist der richtige Interpreter ausgewählt? Ist der Breakpoint überhaupt auf einer ausführbaren Zeile gesetzt? Gerade bei wechselnden virtuellen Umgebungen ist der falsche Interpreter einer der häufigsten Gründe dafür, dass sich das Verhalten nicht so anfühlt wie erwartet.

  • Erweiterung prüfen: Ohne aktivierte Python-Debugger-Erweiterung startet die Session nicht wie gedacht.
  • Interpreter abgleichen: Der Debugger nutzt standardmäßig den für den Workspace gewählten Interpreter.
  • Typ kontrollieren: In modernen Setups sollte type auf debugpy stehen, nicht auf den alten Wert python.
  • Watch-Ausdrücke bereinigen: Ungültige Ausdrücke in der Watch-Ansicht können eine Session unnötig stören.
  • Breakpoints validieren: Nicht ausführbare Zeilen werden vom Debugger oft auf die nächste sinnvolle Stelle verschoben.
  • Thread-Sonderfälle beachten: Bei nativen Threads kann debugpy.debug_this_thread() nötig sein.

Bei Attach-Problemen auf Linux kann außerdem die Systemkonfiguration rund um ptrace_scope eine Rolle spielen. Das ist kein typischer Anwendungsfehler, aber genau deshalb wird es gerne übersehen, wenn der Debugger beim Anhängen an einen laufenden Prozess einfach hängen bleibt oder mit Timeout abbricht. Ich halte solche Systemursachen erst dann für relevant, wenn die Grundkonfiguration schon sauber aussieht.

Oft ist die richtige Reihenfolge also wichtiger als die nächste zusätzliche Option: Erst Startweg, dann Interpreter, dann Breakpoint, dann Spezialfall. Genau so bleibt Debugging beherrschbar und wird nicht zur Suche nach dem einen geheimen Schalter.

Was in der Praxis den größten Unterschied macht

Am Ende ist Debugging in VS Code dann am stärksten, wenn es kurz, reproduzierbar und sichtbar bleibt. Ich will einen klaren Startpunkt, einen passenden Haltepunkt und einen Weg, Variablen ohne Rätselraten zu prüfen. Sobald das Projekt größer wird, sind saubere Konfigurationen und passende Debug-Profile nicht mehr Komfort, sondern Teil der Arbeitsmethode.

Wenn ich ein Python-Projekt aufräume, halte ich deshalb immer drei Dinge fest: den korrekten Interpreter, eine kleine, eindeutige launch.json und die Frage, ob ich wirklich launch brauche oder doch attach. Genau dort geht sonst die meiste Zeit verloren. Wer diese Grundlagen einmal sauber eingerichtet hat, debuggt ruhiger, schneller und deutlich nachvollziehbarer.

Für den Alltag reicht oft schon diese Haltung: nicht mehr Optionen sammeln, sondern die wenigen wirklich relevanten sauber beherrschen.

Häufig gestellte Fragen

Der Debugger ermöglicht es, den Code an bestimmten Stellen anzuhalten, Variablenwerte zu inspizieren und den Programmfluss Schritt für Schritt zu verfolgen. Das ist präziser als print-Statements, besonders bei komplexen Schleifen oder Funktionsaufrufen, da es den genauen Zustand und die Ursache eines Fehlers aufzeigt.
"Launch" startet das Python-Programm direkt aus VS Code heraus, während "attach" den Debugger mit einem bereits laufenden Python-Prozess verbindet. "Launch" ist ideal für die lokale Entwicklung, während "attach" für Remote-Debugging, Container oder extern gestartete Prozesse verwendet wird.
Bedingte Breakpoints sind nützlich, wenn ein Fehler nur unter bestimmten Bedingungen auftritt (z.B. in einer Schleife nach X Durchläufen oder bei einem spezifischen Variablenwert). Logpoints sind ideal, um Informationen in die Debug-Konsole zu schreiben, ohne die Programmausführung anzuhalten, was bei der Beobachtung von Variablenverläufen hilfreich ist.
Prüfen Sie zuerst, ob die Python-Debugger-Erweiterung installiert und aktiviert ist, der korrekte Python-Interpreter ausgewählt wurde und der Breakpoint auf einer ausführbaren Zeile liegt. Stellen Sie sicher, dass "type" in der launch.json auf "debugpy" steht und nicht auf den alten Wert "python".

Artikel bewerten

Durchschnitt: 0.0 / 5 · 0 Bewertungen

Tags

python debugger vscode python debugger vs code einrichten vs code python debugging tipps launch.json python debugger
Autor Darius Götz
Darius Götz
Ich bin Darius Götz und beschäftige mich seit über zehn Jahren intensiv mit den Themen Informatik, Naturwissenschaften und modernen Technologien. In dieser Zeit habe ich als Fachredakteur und Branchenanalyst umfangreiche Kenntnisse über die neuesten Entwicklungen und Trends in diesen Bereichen erworben. Mein Ziel ist es, komplexe Daten und Informationen verständlich und zugänglich zu machen, damit Leser die Zusammenhänge besser erkennen können. Ich spezialisiere mich auf die Analyse von technologischen Innovationen und deren Auswirkungen auf verschiedene Industrien. Dabei lege ich großen Wert auf objektive Berichterstattung und umfassende Faktenüberprüfung, um sicherzustellen, dass die Informationen, die ich präsentiere, sowohl präzise als auch aktuell sind. Mein Engagement gilt der Bereitstellung vertrauenswürdiger Inhalte, die den Lesern helfen, informierte Entscheidungen zu treffen und ein tieferes Verständnis für die Welt der Technologie und Wissenschaft zu entwickeln.

Kommentare (0)

Kommentar hinzufügen