Remote Debugging Python with VSCode

Posted on Fri 24 January 2025 in Python • 3 min read

When your Python code runs on a remote server, inside a container, or in a subprocess that you can't launch directly from VSCode, you need a way to attach the debugger to an already-running process. The debugpy library makes this straightforward.

This is particularly useful for:

  • Debugging ML training jobs on remote GPU servers
  • Debugging code running in Docker containers
  • Debugging worker processes spawned by a parent application
  • Any situation where you can't use VSCode's "Run and Debug" directly

Setup

Step 1: Install debugpy

In your project's environment (local and remote if applicable):

pip install debugpy

Step 2: Create launch.json

In your VSCode project, create or update .vscode/launch.json:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Attach",
            "type": "debugpy",
            "request": "attach",
            "connect": {
                "host": "localhost",
                "port": 5678
            },
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}",
                    "remoteRoot": "."
                }
            ]
        }
    ]
}

Key settings:

  • host: Use localhost for local processes, or the remote server's IP/hostname
  • port: Must match the port in your Python code (5678 is the convention)
  • pathMappings: Maps remote file paths to local paths so breakpoints work correctly

Step 3: Add debugpy to Your Script

At the point where you want to start debugging, add:

import debugpy

debugpy.listen(("localhost", 5678))
print("Waiting for debugger to attach...")
debugpy.wait_for_client()

For remote servers, use 0.0.0.0 to accept connections from any interface:

debugpy.listen(("0.0.0.0", 5678))

Workflow

  1. Run your script in the terminal (or however it's normally launched): bash python your_script.py

  2. The script prints "Waiting for debugger to attach..." and pauses at wait_for_client()

  3. In VSCode, go to Run and Debug (Ctrl+Shift+D), select "Python: Attach", and click the green play button

  4. The script resumes execution and stops at your breakpoints

Remote Server Example

If debugging on a remote server, you need SSH port forwarding.

On your local machine:

ssh -L 5678:localhost:5678 user@remote-server

Then run your script on the remote server. VSCode connects to localhost:5678, which SSH forwards to the remote server.

Update launch.json for remote paths:

{
    "pathMappings": [
        {
            "localRoot": "${workspaceFolder}",
            "remoteRoot": "/home/user/project"
        }
    ]
}

Tips for ML Training Debugging

When debugging long-running training jobs:

  1. Conditional debugging: Only wait for debugger in specific conditions: python import os if os.environ.get("DEBUG"): import debugpy debugpy.listen(("0.0.0.0", 5678)) debugpy.wait_for_client()

  2. Don't block training: Remove wait_for_client() if you want to attach optionally: python debugpy.listen(("0.0.0.0", 5678)) # Script continues, attach debugger whenever ready

  3. Set breakpoints before attaching: VSCode sends breakpoint information when you attach, so set them first.

Troubleshooting

Connection refused

  • Verify the port matches between script and launch.json
  • Check firewall settings on remote servers
  • Ensure SSH port forwarding is active for remote debugging

Breakpoints not hitting

  • Verify pathMappings correctly maps remote to local paths
  • Ensure the file paths in VSCode match the mapped paths
  • Try adding an explicit debugpy.breakpoint() in your code

debugpy import error

  • Install debugpy in the same environment where your script runs
  • For containers, ensure debugpy is in your requirements.txt or Dockerfile

Remote debugging is essential when print statements aren't enough and you need to inspect variables, step through code, and understand program flow in complex scenarios.