NeoVim LSP and DAP for Python (and Django)

One of the most read article of my blog is my guide about how to configure LSP for PHP but this time is for Python!

In this guide we will see how to configure everything that works with Poetry (as we are using various wrappers, it will works also with Conda or Venv) and PyLSP, with DebugPy installed in the same virtual environment of the Django project.
This decision to have everything in the same Venv simplify a lot, avoid conflicts and allows a nicer integration with the various tools like Flake8 or MyPy.

Neovim plugins to install

For LSP you need:

For DAP you need:

LSP settings

The py_lsp.nvim plugin got 2 pull requests by me that improve the LSP server detection inside the Venv with more alerts and settings for pylsp plugins.

    language_server = "pylsp",
    source_strategies = {"poetry", "default", "system"},
    capabilities = capabilities,
    on_attach = on_attach,
    pylsp_plugins = {
        autopep8 = {
            enabled = true
        pyls_mypy = {
            enabled = true
        pyls_isort = {
            enabled = true
        flake8 = {
            enabled = true,
            executable = ".venv/bin/flake8",

With this piece of code as you can see we are defining the source strategies that the plugin will use to find Python and also the LSP, the language server and the plugins enabled (you can change those as you need) in pylsp.
The capabilities and on_attach properties are something that you can customize with plugins or custom code, so if you have no idea you can remove those 2 lines as it will use the defaults one.

Anyway with the latest plugin version, automatically, when you are in a Python project or in a file, it will load everything from the Venv (also lsp if is installed) otherwise will use the global one in your machine.
The purpose of this plugin is the automatic path detection for python (and the packages) otherwise you have to code it manually in your configuration.

To get the better from neovim and avoid problems is better to launch from the folder where is the project, otherwise you can try with the :PyLSPReloadVenv command that will recheck the path etc.

Also doesn’t forget to run :TSinstall python in this way your treesitter module will have the python support.

DAP settings

Taking experience from this ticket I was able to write the best settings that let’s to use NeoVim as IDE and run Django from the editor itself.

I suggest to get the latest version from by dotfiles as can change and I don’t update this article:

local pythonPath = function()
    local cwd = vim.loop.cwd()
    if vim.fn.executable(cwd .. '/.venv/bin/python') == 1 then
        return cwd .. '/.venv/bin/python'
        return '/usr/bin/python'

local set_python_dap = function()
    require('dap-python').setup() -- earlier so setup the various defaults ready to be replaced
    dap.configurations.python = {
            type = 'python';
            request = 'launch';
            name = "Launch file";
            program = "${file}";
            pythonPath = pythonPath()
            type = 'python',
            request = 'launch',
            name = 'DAP Django',
            program = vim.loop.cwd() .. '/',
            args = {'runserver', '--noreload'},
            justMyCode = true,
            django = true,
            console = "integratedTerminal",
            type = 'python';
            request = 'attach';
            name = 'Attach remote';
            connect = function()
                return {
                    host = '',
                    port = 5678
            type = 'python';
            request = 'launch';
            name = 'Launch file with arguments';
            program = '${file}';
            args = function()
                local args_string = vim.fn.input('Arguments: ')
                return vim.split(args_string, " +")
            console = "integratedTerminal",
            pythonPath = pythonPath()

    dap.adapters.python = {
        type = 'executable',
        command = pythonPath(),
        args = {'-m', 'debugpy.adapter'}

vim.api.nvim_create_autocmd({"DirChanged"}, {
    callback = function() set_python_dap() end,

In this code you can see a function to do the python path detection for Venv (something that the LSP plugin was automatically doing for you), next step is a custom function that will be executed on start and on directory changed. The function will overwrite the various run modes for the Python language with support for the pythonPath function we created above, also we add the DAP Django and the adapter command for DebugPy.

We specify also to add DAP support only in our projects and not in the dependencies and Django support (debugpy has a parameter for that but I wasn’t able to find what does).

So in your Neovim you just need to run DAP Django and you will have the server running and you can inspecting:

The next step is to run neovim in the right environment, you can’t run neovim inside the venv because you probably doesn’t have some stuff needed by your plugins and so on.
The suggestion is to check carefully and do your tests.


It was more simpler than I thought after reading various dotfiles, configuration preset and tutorial/documentation.
With this plugins and integration everything will be simplified but I didn’t mentioned the mappings for DAP as I invite you to read the readme and create your own mappings (mine are there).

Why PyLSP instead of Pyright? Well I was already using it with Spyder so in this way I have the same LSP everywhere but this solutions works also with the other LSP (everyone is different about plugins and tools supported).

If you are looking for instructions on how to get a single NeoVim instance just read here. This script saves me, because detect automatically the folder where I am trying to execute nvim and if find a .venvin the same folder, activate the venv just for neovim and everything works.

Liked it? Take a second to support Mte90 on Patreon!
Become a patron at Patreon!

Leave a Reply

Your email address will not be published. Required fields are marked *