Skip to main content

🪲 Python Debugging

Learn how to set up Python debugging in Neovim that works with venv-selector's virtual environment switching.

🚀 Quick Overview

When you switch virtual environments with venv-selector, your debugging setup should automatically use the correct Python interpreter and installed packages.

How venv-selector helps

If mfussenegger/nvim-dap and mfussenegger/nvim-dap-python are installed, venv-selector automatically updates nvim-dap with the new Python path every time you switch virtual environments.

🎯 🛠️ nvim-dap Setup

Prerequisites

📦 Required Plugins

Install these plugins using your preferred plugin manager:

-- Using lazy.nvim
{
"mfussenegger/nvim-dap",
dependencies = {
"mfussenegger/nvim-dap-python",
},
}
-- Using packer.nvim
use {
"mfussenegger/nvim-dap",
requires = {
"mfussenegger/nvim-dap-python",
},
}
🐍 Install debugpy

You need debugpy installed in each virtual environment you want to debug:

# In your virtual environment
pip install debugpy
Virtual Environment Requirement

debugpy must be installed in the virtual environment you're debugging. When you switch environments with venv-selector, make sure debugpy is available in the new environment.

Global Installation

You can also install debugpy globally or in a dedicated debug environment:

# Create dedicated debug environment
python -m venv ~/.virtualenvs/debugpy
source ~/.virtualenvs/debugpy/bin/activate
pip install debugpy

Basic Configuration

⚙️ nvim-dap-python Setup

Add this to your Neovim configuration:

-- Basic setup
require('dap-python').setup('python') -- Uses the python in PATH

-- OR: Use a dedicated debugpy environment
require('dap-python').setup('~/.virtualenvs/debugpy/bin/python')

How venv-selector integration works:

  • When you switch virtual environments, venv-selector automatically updates nvim-dap
  • The Python path in your debugging configurations gets updated
  • Your breakpoints and debug sessions use the correct interpreter
🎮 Keybindings

Set up keybindings for debugging:

-- Debugging keybindings
vim.keymap.set('n', '<Leader>db', function() require('dap').toggle_breakpoint() end, { desc = "Toggle Breakpoint" })
vim.keymap.set('n', '<Leader>dc', function() require('dap').continue() end, { desc = "Continue" })
vim.keymap.set('n', '<Leader>do', function() require('dap').step_over() end, { desc = "Step Over" })
vim.keymap.set('n', '<Leader>di', function() require('dap').step_into() end, { desc = "Step Into" })
vim.keymap.set('n', '<Leader>dr', function() require('dap').repl.open() end, { desc = "Open REPL" })

-- Python-specific
vim.keymap.set('n', '<Leader>dpr', function() require('dap-python').test_method() end, { desc = "Test Method" })
vim.keymap.set('n', '<Leader>dpc', function() require('dap-python').test_class() end, { desc = "Test Class" })

Usage

  1. Set breakpoints by placing your cursor on a line and pressing <Leader>db
  2. Start debugging by pressing <Leader>dc
  3. Step through code using <Leader>do (over) or <Leader>di (into)
  4. Inspect variables in the REPL with <Leader>dr

🔧 Troubleshooting

Common Issues and Solutions

Issue: "No module named 'debugpy'"

Solution: Install debugpy in the active virtual environment:

pip install debugpy

Issue: Breakpoints not working

Causes and solutions:

  1. Wrong Python interpreter: Verify with :lua print(require("venv-selector").python())
  2. debugpy not in venv: Install debugpy in the current virtual environment
  3. Path issues: Use absolute paths in debug configurations

Issue: Environment variables not available

Solution: Ensure venv-selector has activated the environment:

-- Check current environment
:lua print(require("venv-selector").venv())
🔍 Debug Information Commands

Use these commands to troubleshoot debugging issues:

-- Check current Python interpreter
:lua print(require("venv-selector").python())

-- Check virtual environment path
:lua print(require("venv-selector").venv())

-- Check DAP configurations
:lua print(vim.inspect(require('dap').configurations.python))

-- Open DAP REPL for interactive debugging
:lua require('dap').repl.open()

🚀 Advanced Configuration

Automatic Virtual Environment Detection

Auto-configure debugpy Path

Automatically use the correct Python interpreter for debugging:

-- Auto-setup function
local function setup_python_dap()
local python = require("venv-selector").python()
if python then
require('dap-python').setup(python)
end
end

-- Setup after venv selection
vim.api.nvim_create_autocmd("User", {
pattern = "VenvSelectPost", -- If this event exists
callback = setup_python_dap,
})

-- Or call it manually after switching environments
vim.keymap.set('n', '<Leader>ds', setup_python_dap, { desc = "Setup Python DAP" })

Custom Debug Configurations

🎛️ Advanced DAP Configurations

Add custom debug configurations for different scenarios:

require('dap').configurations.python = {
{
type = 'python',
request = 'launch',
name = 'Launch current file',
program = '${file}',
pythonPath = function()
return require("venv-selector").python() or 'python'
end,
},
{
type = 'python',
request = 'launch',
name = 'Launch with arguments',
program = '${file}',
args = function()
local args_string = vim.fn.input('Arguments: ')
return vim.split(args_string, " ", true)
end,
pythonPath = function()
return require("venv-selector").python() or 'python'
end,
},
{
type = 'python',
request = 'launch',
name = 'Run pytest',
module = 'pytest',
args = {'${file}'},
pythonPath = function()
return require("venv-selector").python() or 'python'
end,
},
}

📚 Additional Resources

Best Practices
  1. Install debugpy in your virtual environments
  2. Use the automatic Python path detection for seamless venv switching
  3. Set up keybindings that work with your workflow
  4. Test your debug setup with a simple script before complex projects
Integration with venv-selector

When you switch virtual environments with :VenvSelect, your debugging automatically uses the correct Python interpreter and has access to all packages in that environment.