Debugging Python in VSCode in a Robust Way

May 29, 2023 · 2 minute read

A handy debugging configuration that I use daily. This setup fixes two sources of frustration when developing in python:

  1. OS (environment) fixed with Docker, specifically VSCode Dev Container
  2. Python dependencies resolved with pipenv

TLDR;

The whole idea is to get a solid Python debugging setup in VSCode, which we’ll outline in a launch.json file. We’re doing this inside a VSCode Dev Container, keeping things clean and isolated. To keep Python version dependencies under control, add the following Dockerfile:

...
COPY Pipfile .
RUN pipenv lock && pipenv install --python 3 --system

Here’s how the debugging configuration looks for a directory structure where all relevant code resides in src, following Cookiecutter Data Science

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "src",
            "type": "python",
            "request": "launch",
            "cwd": "${workspaceFolder}/src",
            "program": "${file}",
            "console": "integratedTerminal",
            "autoReload": {
                "enable": true
            },
            "env": {
                "PYTHONPATH": "${workspaceFolder}/src"
            }
        }
    ]
}

Prerequisites

  1. Visual Studio Code
  2. Python extension for VSCode
  3. (optional) VSCode Dev Containers

Step-by-Step Tutorial

Step 1: Setting Up the Dev Container

Kick things off by setting up a Dev Container for your Python project. Refer to vscode documentation . Managing python dependencies becomes easier by 1., fixing the environment defined by a Dockerfile, and 2., resolving python dependencies using pipenv:

FROM python:3.9-slim

WORKDIR /app

RUN pip3 install --upgrade pip && \
    pip3 install pipenv black pre-commit mypy ruff isort debugpy

COPY Pipfile .
RUN pipenv lock && pipenv install --python 3 --system

This trick handles Python version dependencies smoothly.

Step 2: Defining the Debug Configuration

Next, we need to define our debug configuration. This goes into a launch.json file in the .vscode directory. We set the program attribute to ${file} so VSCode knows to execute the currently active file. We also set the cwd attribute to ${workspaceFolder}/src to keep things running in the right context. The debugger’s auto-reload feature is switched on, and we add the src directory to the PYTHONPATH.

Step 3: Running and Debugging Python Code

With the setup ready, open any Python file in your project and start debugging directly in VSCode.

Conclusion

This setup is a practical way to debug Python modules in VSCode, especially for projects that look a bit like the Cookiecutter Data Science project structure. The idea is to keep the debugging process as integrated as possible with your coding workflow and project structure. And this configuration does just that. Enjoy crafting!