# How to Debug a Python Module in Visual Studio Code by Configuring launch.json

> Debug Python modules in VS Code by configuring launch.json. Learn to use the module key for effective debugging with full import context and namespace preservation.

- Repository: [Python/cpython](https://github.com/python/cpython)
- Tags: how-to-guide
- Published: 2026-02-16

---

**To debug a Python module in VS Code, configure your [`launch.json`](https://github.com/python/cpython/blob/main/launch.json) with the `"module"` key instead of `"program"`, which instructs the debugger to execute your code via `python -m` while preserving the full module import context and namespace.**

When working with the `python/cpython` repository or any Python project structured as a package, you need to debug modules rather than standalone scripts. The official Python extension for VS Code uses **debugpy** to communicate with the CPython interpreter, and proper [`launch.json`](https://github.com/python/cpython/blob/main/launch.json) configuration ensures the debugger correctly initializes the module import machinery.

## Understanding the Python Debugger Architecture in VS Code

### How CPython Handles Breakpoints

The debugging workflow in VS Code ultimately relies on CPython's internal breakpoint implementation. When you set a breakpoint in the editor, the debugger interfaces with several key components of the CPython source:

- **[`Python/bltinmodule.c`](https://github.com/python/cpython/blob/main/Python/bltinmodule.c)**: Implements the built-in `breakpoint()` function, which calls `sys.breakpointhook()` by default.
- **[`Python/sysmodule.c`](https://github.com/python/cpython/blob/main/Python/sysmodule.c)**: Contains the `sys.breakpointhook` implementation that routes to `pdb.set_trace()`.
- **[`Lib/pdb.py`](https://github.com/python/cpython/blob/main/Lib/pdb.py)**: The pure-Python debugger that provides the interactive REPL used by VS Code when execution pauses.

### The Role of debugpy in Module Execution

The **debugpy** engine launches the CPython interpreter as a subprocess and communicates via the Debug Adapter Protocol. When debugging a module, debugpy must invoke the interpreter with the `-m` flag to trigger the module import system (`importlib._bootstrap._gcd_import`) rather than treating the target as a file path. This distinction is critical for packages that rely on relative imports or specific `__main__` block execution.

## Configuring launch.json to Debug a Python Module

### The Module Launch Configuration

To debug a Python module within Visual Studio Code using the python debugger vscode by configuring the launch dot json file effectively, you must specify the `"module"` attribute. This replaces the standard `"program"` attribute used for script debugging.

### Essential Parameters for Module Debugging

The following configuration keys align your debugging session with CPython's internal architecture:

- **`"type": "python"`** – Selects the debugpy adapter that interfaces with the CPython interpreter.
- **`"request": "launch"`** – Starts a fresh CPython process, loading the module's `__main__` namespace.
- **`"module"`** – Specifies the fully-qualified module name (e.g., `"mypackage.mymodule"`), triggering `python -m` execution.
- **`"cwd"`** – Sets the working directory, affecting `sys.path` and relative import resolution.
- **`"justMyCode": false`** – Allows stepping into CPython standard library code (e.g., [`Lib/pdb.py`](https://github.com/python/cpython/blob/main/Lib/pdb.py)) rather than skipping it.
- **`"console": "integratedTerminal"`** – Preserves terminal I/O behavior that `pdb` expects for interactive debugging.

### Recommended launch.json Configuration

```json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug Python Module",
            "type": "python",
            "request": "launch",
            "module": "mypackage.mymodule",
            "cwd": "${workspaceFolder}",
            "env": {
                "PYTHONPATH": "${workspaceFolder}"
            },
            "justMyCode": false,
            "console": "integratedTerminal",
            "stopOnEntry": false
        }
    ]
}

```

## Step-by-Step Implementation

### Setting Up Your Workspace

Ensure your project structure follows standard Python package conventions with an [`__init__.py`](https://github.com/python/cpython/blob/main/__init__.py) file in each directory. The `PYTHONPATH` environment variable in your [`launch.json`](https://github.com/python/cpython/blob/main/launch.json) should point to the workspace root so that `importlib` can locate your module during the debug session.

### Creating the Debug Configuration

1. Open the Run and Debug view in VS Code (Ctrl+Shift+D).
2. Click "create a launch.json file" and select the Python environment.
3. Replace the default configuration with the module-specific settings shown above, substituting `"mypackage.mymodule"` with your actual module path.

### Running the Debugger

With your configuration saved, place a breakpoint in your module code and press **F5**. The debugger will execute `python -m mypackage.mymodule`, initialize the CPython interpreter, and pause at your breakpoint. You can then inspect variables, step through the call stack, and even descend into the standard library implementation in [`Lib/pdb.py`](https://github.com/python/cpython/blob/main/Lib/pdb.py) if `"justMyCode"` is disabled.

## Advanced Configuration Options

### Debugging into CPython Internals

Setting `"justMyCode": false` is essential when you need to trace execution into the Python standard library or investigate how `breakpoint()` behaves. This setting allows you to step through the implementation in [`Lib/pdb.py`](https://github.com/python/cpython/blob/main/Lib/pdb.py) and observe how `sys.breakpointhook` (defined in [`Python/sysmodule.c`](https://github.com/python/cpython/blob/main/Python/sysmodule.c)) routes control to the debugger.

### Custom Breakpoint Hooks

CPython supports custom breakpoint hooks via the `PYTHONBREAKPOINT` environment variable. You can configure this in your [`launch.json`](https://github.com/python/cpython/blob/main/launch.json) to override the default `pdb.set_trace()` behavior:

```json
"env": {
    "PYTHONBREAKPOINT": "custom_debug_hook"
}

```

Your custom function will receive control whenever `breakpoint()` is called, allowing you to log stack traces or implement conditional debugging logic before entering the interactive session.

### Remote Debugging Considerations

For scenarios involving remote debugging, CPython provides low-level support in [`Python/remote_debugging.c`](https://github.com/python/cpython/blob/main/Python/remote_debugging.c) and defines debug cookies in [`Include/internal/pycore_debug_offsets.h`](https://github.com/python/cpython/blob/main/Include/internal/pycore_debug_offsets.h). While VS Code typically handles local debugging via `debugpy`, you can configure remote attachment by adding a `"connect"` block to your [`launch.json`](https://github.com/python/cpython/blob/main/launch.json):

```json
"connect": {
    "host": "localhost",
    "port": 5678
}

```

This connects to a CPython process already running with the debug server enabled, utilizing the same breakpoint infrastructure defined in [`bltinmodule.c`](https://github.com/python/cpython/blob/main/bltinmodule.c) and [`sysmodule.c`](https://github.com/python/cpython/blob/main/sysmodule.c).

## Summary

- **Use the `"module"` key** in [`launch.json`](https://github.com/python/cpython/blob/main/launch.json) to debug Python packages via `python -m` execution, ensuring proper import context and `__main__` block handling.
- **Set `"justMyCode": false`** to step into CPython standard library code, including the [`pdb.py`](https://github.com/python/cpython/blob/main/pdb.py) implementation and `sys.breakpointhook` internals.
- **Configure environment variables** like `PYTHONPATH` and `PYTHONBREAKPOINT` in your launch configuration to match command-line behavior and customize debugging hooks.
- **Leverage `"console": "integratedTerminal"`** to preserve interactive I/O required by `pdb` and other console-based debuggers.
- **Reference CPython source files** ([`bltinmodule.c`](https://github.com/python/cpython/blob/main/bltinmodule.c), [`sysmodule.c`](https://github.com/python/cpython/blob/main/sysmodule.c), [`pdb.py`](https://github.com/python/cpython/blob/main/pdb.py)) to understand how breakpoints are triggered and handled by the VS Code debugger.

## Frequently Asked Questions

### How do I debug a Python module instead of a script in VS Code?

To debug a Python module, open your [`.vscode/launch.json`](https://github.com/python/cpython/blob/main/.vscode/launch.json) file and create a configuration using `"type": "python"` and `"request": "launch"`, but specify `"module": "yourpackage.module"` instead of `"program"`. This tells the debugger to execute `python -m yourpackage.module`, preserving the module import context and allowing relative imports to resolve correctly.

### What is the purpose of the "justMyCode" setting in launch.json?

The `"justMyCode": false` setting allows the debugger to step into code outside your workspace, including the Python standard library. When debugging CPython internals or investigating how `breakpoint()` works, disabling this setting lets you trace execution through [`Lib/pdb.py`](https://github.com/python/cpython/blob/main/Lib/pdb.py) and observe how `sys.breakpointhook` in [`Python/sysmodule.c`](https://github.com/python/cpython/blob/main/Python/sysmodule.c) routes control to the interactive debugger.

### How does VS Code's debugger connect to CPython's breakpoint system?

VS Code uses the **debugpy** adapter, which launches CPython as a subprocess and communicates via the Debug Adapter Protocol. When your code calls `breakpoint()`, CPython's built-in function (implemented in [`Python/bltinmodule.c`](https://github.com/python/cpython/blob/main/Python/bltinmodule.c)) invokes `sys.breakpointhook()`, which defaults to `pdb.set_trace()` from [`Lib/pdb.py`](https://github.com/python/cpython/blob/main/Lib/pdb.py). The debugpy adapter intercepts this interaction and maps it to the VS Code debugging UI, allowing you to inspect variables and control execution flow.