Debug Python in VS Code: Complete Beginner Guide

Published on: July 10, 2026
Reading time: 8 minutes
Debug de aplicações Python no Visual Studio Code

When a Python program runs but produces the wrong result, adding more print() calls can quickly become confusing. A debugger lets you pause the program, inspect values, execute one line at a time, and understand exactly how the code reached its current state. This guide shows how to debug Python in VS Code using the current Microsoft Python debugging tools.

You will learn how to select the correct interpreter, set breakpoints, start a debugging session, use Step Over and Step Into, inspect variables and the call stack, create conditional breakpoints and logpoints, configure launch.json, and diagnose common problems.

For terminal-based debugging without an editor, see the Python pdb guide. Automated tests also reduce the amount of manual debugging required; the Python unit testing guide explains that workflow.

What You Need

Install Visual Studio Code, Python, and the Microsoft Python extension. The Python Debugger extension provides the debug adapter used by current VS Code Python sessions and is normally installed as a dependency of the Python extension.

The official VS Code Python debugging documentation describes the available configurations and controls. The Microsoft Python extension page lists its editor, environment, testing, and debugging integrations.

Open a Project Folder

Open the folder containing your Python files rather than opening only one file. A workspace folder gives VS Code a stable location for settings, virtual environments, and the .vscode/launch.json configuration.

Create a file named shopping_cart.py:

def calculate_total(prices, discount=0):
    subtotal = sum(prices)
    discount_value = subtotal * discount
    return subtotal - discount_value


items = [19.90, 5.50, 12.00]
final_total = calculate_total(items, discount=10)
print(f"Total: ${final_total:.2f}")

The code contains a logic error: the function expects a decimal discount such as 0.10, but the caller passes 10. The program is syntactically valid, so Python runs it and prints an incorrect negative total.

Select the Correct Python Interpreter

Use the interpreter indicator in the VS Code status bar or run Python: Select Interpreter from the Command Palette. Choose the environment where your packages are installed.

Using the wrong interpreter can cause missing-package errors, an unexpected Python version, or different environment variables. When a project uses a virtual environment, select that environment before debugging.

Set Your First Breakpoint

Click in the gutter to the left of the line number beside:

discount_value = subtotal * discount

A red dot marks the breakpoint. When execution reaches that line, the debugger pauses before running it. You can also toggle a breakpoint on the current line with F9.

Start a Debugging Session

Open shopping_cart.py, then use Run and Debug or press F5. For a simple file, choose the Python file configuration when prompted.

When the breakpoint is reached, VS Code highlights the current line and opens the debugging interface. The left sidebar normally displays Variables, Watch, Call Stack, and Breakpoints. The Debug Console accepts expressions evaluated in the paused context.

Inspect Variables

At the breakpoint, inspect:

  • prices: the input list.
  • discount: currently 10.
  • subtotal: the sum of the prices.

The unexpected discount value identifies the bug. Change the function call to:

final_total = calculate_total(items, discount=0.10)

Variable inspection is especially useful when values depend on several branches or loops. The Python variable scope guide explains why local, enclosing, global, and built-in names may appear in different frames.

Use the Main Debug Controls

ControlTypical shortcutWhat it does
ContinueF5Runs until the next breakpoint or program end.
Step OverF10Executes the current line without entering called functions.
Step IntoF11Enters a function called on the current line.
Step OutShift + F11Finishes the current function and returns to its caller.
RestartToolbarStarts the session again.
StopShift + F5Ends the debugging session.

Shortcuts can vary by operating system and keymap. The toolbar icons are always available during a session.

Understand Step Over vs. Step Into

Consider this program:

def apply_tax(amount, rate):
    return amount * (1 + rate)


def create_invoice(prices):
    subtotal = sum(prices)
    total = apply_tax(subtotal, 0.08)
    return total


print(create_invoice([10, 20, 30]))

When paused on the line calling apply_tax(), Step Over calculates the result and remains in create_invoice(). Step Into opens apply_tax() so you can inspect amount and rate.

Use the Watch Panel

A watch expression is recalculated whenever execution pauses. Useful expressions include:

subtotal * discount
len(prices)
subtotal - discount_value
all(price >= 0 for price in prices)

Watch expressions are helpful when the value you care about is not stored in a variable. Avoid expressions with side effects because evaluating them can change program state.

Use the Debug Console

While paused, evaluate Python expressions in the Debug Console:

subtotal
prices[0]
type(discount)
subtotal * 0.10

The console is an inspection tool, not a replacement for permanent fixes. Changes made during a session disappear when the program restarts.

Read the Call Stack

The call stack shows how execution reached the current line. In a nested program, it may display:

main
create_report
calculate_average
validate_values

Selecting a frame changes the local variables shown for that function. This is valuable when an error occurs far from the original caller or when the same function is used from several places.

Create Conditional Breakpoints

A normal breakpoint pauses every time. In a loop with thousands of iterations, add a condition so it pauses only for a specific state.

orders = [15, 42, -8, 27, 100]

for index, amount in enumerate(orders):
    processed = amount * 1.1
    print(index, processed)

Right-click the breakpoint and choose Edit Breakpoint. Example conditions:

amount < 0
index == 3
processed > 50

Conditional breakpoints are ideal for invalid records, rare states, and later loop iterations.

Use Hit Counts

A hit-count breakpoint pauses after the line has been reached a chosen number of times. This is useful when a problem appears only after repeated calls. Depending on the debug interface, you can set a comparison such as pausing when the hit count equals or exceeds a value.

Use Logpoints Without Changing Code

A logpoint writes a message to the Debug Console instead of pausing. It is useful when you want temporary diagnostic output but do not want to add and later remove print() calls.

Example log message:

Processing order {index}: amount={amount}

For persistent application diagnostics, use the Python logging module. Logpoints are editor configuration; logging remains in the application and can write to files or monitoring systems.

Debug Exceptions

VS Code can pause when exceptions are raised. Open the Breakpoints section and enable the relevant exception options. This lets you inspect variables at the point of failure rather than only reading the final traceback.

def average(values):
    return sum(values) / len(values)


print(average([]))

Pausing on the resulting ZeroDivisionError shows that values is empty. The traceback and call stack then explain where the empty list originated.

A SyntaxError happens before normal execution can begin, so breakpoints cannot fix invalid syntax. Use the Python SyntaxError guide to read those messages.

Create a launch.json Configuration

Simple files can be debugged without configuration. Create .vscode/launch.json when you need arguments, a module, environment variables, a different working directory, or another launch behavior.

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug current Python file",
      "type": "debugpy",
      "request": "launch",
      "program": "${file}",
      "console": "integratedTerminal",
      "justMyCode": true
    }
  ]
}

program selects the file, console chooses where input and output appear, and justMyCode controls whether stepping normally skips library internals.

Pass command-line arguments

{
  "name": "Debug report command",
  "type": "debugpy",
  "request": "launch",
  "program": "${workspaceFolder}/report.py",
  "args": ["sales.csv", "--format", "json"],
  "console": "integratedTerminal"
}

This pattern is useful for the Python CLI with argparse created later in this batch.

Add non-secret environment values

{
  "env": {
    "APP_ENV": "development"
  }
}

Do not commit passwords or API tokens inside launch.json. Use environment management appropriate to the project and keep secrets outside version control.

Debug Tests

The Testing view can discover and run unittest or pytest tests. Set a breakpoint inside the application or test, then use the debug action beside a test. This combines repeatable test inputs with interactive variable inspection.

The dedicated Pytest beginner guide explains assertions, exception tests, organization, and useful commands.

Common Debugging Problems

The breakpoint is gray or unverified

Confirm that the file being executed is the file containing the breakpoint, save the file, and verify the selected interpreter and launch configuration.

VS Code cannot import a package

Select the environment where the package is installed. Check the interpreter path in the status bar and compare it with the terminal command used for installation.

Input does not work

Use the integrated terminal for programs that call input(). A Debug Console is not always the correct place for interactive terminal input.

The debugger enters library code

Keep justMyCode enabled for ordinary application debugging. Disable it only when you intentionally need to inspect a dependency.

The program behaves differently in debugging

Check the working directory, environment variables, arguments, and interpreter. A launch configuration may differ from the command you normally run in a terminal.

A Practical Debugging Routine

  1. Reproduce the problem with the smallest reliable input.
  2. Read the complete error or describe the incorrect result.
  3. Place a breakpoint before the state first becomes suspicious.
  4. Inspect input values and assumptions.
  5. Step through one decision at a time.
  6. Use the call stack to find the original caller.
  7. Fix the cause rather than only the final symptom.
  8. Add a test that fails before the fix and passes afterward.
  9. Remove temporary breakpoints and diagnostic output.

Frequently Asked Questions

What is the difference between Run and Debug?

Run executes the program normally. Debug starts it under a debugger so breakpoints, stepping, variable inspection, and exception controls are available.

Can I debug a virtual environment?

Yes. Select its interpreter before starting the session.

Can I change a variable while paused?

The debugger may allow evaluation or assignment in the Debug Console. Treat this as temporary experimentation; update the source code for the permanent fix.

Can I debug imported modules?

Yes. Set breakpoints in project modules. To step into external libraries, adjust justMyCode.

Should I stop using print()?

No. Simple output remains useful. A debugger is better when you need to examine changing state, nested calls, or a precise execution path.

Conclusion

To debug Python in VS Code effectively, start with the correct interpreter, pause before the suspected failure, inspect values, and use stepping and the call stack to follow the program’s decisions. Conditional breakpoints and logpoints make large loops easier to investigate, while launch.json makes complex runs repeatable.

The strongest workflow combines debugging with clear error reading, logging, and automated tests. A debugger explains one execution; a regression test helps prevent the same bug from returning.

Share:

Facebook
WhatsApp
Twitter
LinkedIn

Article content

    Related articles

    Transformando scripts Python em executáveis para Windows
    IDEs and Tools
    Foto de perfil de Leandro Hirt da Academify

    Create Executable Python Scripts Easily

    Learn to create executable Python scripts using PyInstaller: set up a virtual environment, build a single-file .exe, add an icon,

    Ler mais

    Tempo de leitura: 3 minutos
    03/06/2026
    Transformando script Python em executável EXE rapidamente
    IDEs and Tools
    Foto de perfil de Leandro Hirt da Academify

    Convert Python Script to .exe in 5 Minutes

    Convert your Python script to .exe in 5 minutes using PyInstaller: virtual environment setup, single-file build, no-console flag, custom icon,

    Ler mais

    Tempo de leitura: 5 minutos
    03/06/2026
    Publicação de pacote Python no PyPI em poucos minutos
    IDEs and Tools
    Foto de perfil de Leandro Hirt da Academify

    Publish Your Python Package to PyPI in 5 Min

    Learn how to publish your Python package to PyPI in 5 minutes: project structure, pyproject.toml, build, API tokens, Twine upload,

    Ler mais

    Tempo de leitura: 6 minutos
    03/06/2026
    Execução de scripts Python com Docker em containers
    IDEs and Tools
    Foto de perfil de Leandro Hirt da Academify

    Run Your Python Script in Docker in 5 Minutes

    Run your Python script in Docker in 5 minutes: write a Dockerfile, build an image, run a container, pass environment

    Ler mais

    Tempo de leitura: 4 minutos
    31/05/2026
    Gerenciamento de dependências Python com Poetry
    IDEs and Tools
    Foto de perfil de Leandro Hirt da Academify

    Manage Python Dependencies with Poetry

    Learn how to manage Python dependencies with Poetry: install it, add/remove packages, understand poetry.lock, use dev groups, Docker integration, and

    Ler mais

    Tempo de leitura: 4 minutos
    31/05/2026
    Criação de ambiente Conda para projetos Python
    IDEs and Tools
    Foto de perfil de Leandro Hirt da Academify

    Create a Python Conda Environment in Minutes

    Learn how to create a Conda environment for Python in minutes: install Miniconda, activate environments, install packages, export to YAML,

    Ler mais

    Tempo de leitura: 4 minutos
    31/05/2026