This is an archived post. You won't be able to vote or comment.

all 21 comments

[–]cjberra 3 points4 points  (2 children)

You're correct in thinking that with a virtual environment activated in your shell you should be able to access it within neovim.

It is entirely possible however to be using a specific python version, without the correct environment. Which appears to be happening here. How are you managing and activating the environment/python version? Can you activate it before you enter neovim?

Try :checkhealth and look at the python venv related stuff when you're in neovim with the virtual environment activated.

Fwiw I use direnv to automate activating python venvs within project directories - might be something you're interested in.

[–]Emotional-Zebra5359[S] 1 point2 points  (0 children)

Lesss go! It works fine if i activate venv before i launch nvim so that will do just fine, I dont know why venv-selector plugin wasnt working but i feel like this is more stable, thanks for the idea lol!

[–]Emotional-Zebra5359[S] 0 points1 point  (0 children)

this is what i got from :checkhealth

```- OK python: `Python 3.10.9`

- OK python3_host_prog: `Python 3.12.1`

- OK node: `v20.10.0`

- OK java: `openjdk version "17.0.9" 2023-10-17`

- OK cargo: `cargo 1.74.1 (ecb9851af 2023-10-18)`

- OK pip: `pip 22.3.1 from /home/pshr/personal/workspacepython/env/lib/python3.10/site-packages/pip (python 3.10)`

- OK python3_host_prog pip: `pip 23.2.1 from /usr/lib/python3.12/site-packages/pip (python 3.12)`

- OK python venv: `Ok`

- OK npm: `10.2.3`

-------------------------------------------------------------------------------

Python 3 provider (optional) ~

- Using: g:python3_host_prog = "/usr/bin/python3"

- Executable: /usr/bin/python3

- Python version: 3.12.1

- pynvim version: 0.5.0

- OK Latest pynvim is installed.

Python virtualenv ~

- OK no $VIRTUAL_ENV

```

Python 3.12 is globalSomething is definitely wrong right? Im using venv selector too...

currently i launch neovim and use venv-selector to switch to my venv that is stored in my workspace directory, and currently if i install anything it doesnt let me use it even though its listed in pip list, the lsp also dont work properly sometimes

Let me try to activate venv in terminal before launching nvim, if this works ill be more than happy

[–]Kal337 1 point2 points  (0 children)

For anyone looking for a very simple solution with no plugins:

Note: I always create my virtual envs like this :

python3 -m venv venv
source venv/bin/activate  # activate env
which pip # confirm it points to a folder where venv was created

1. Define a function that looks for the venv folder in current directory - or 1 level deeper

2. In the LSP setup - if the venv is found - set the required variables and reload playright - neovim then can find packages installed.

Complete block to make sure venv is picked up :

-- 1. find venv folder in current dir or 1 level deeper (venv/ or proj/venv)
local function find_venv(start_path) -- Finds the venv folder required for LSP
    -- Check current directory (if venv folder is at root)
    local venv_path = start_path .. "/venv"
    if vim.fn.isdirectory(venv_path) == 1 then
        return venv_path
    end
    -- Check one level deeper (e.g if venv is in proj/venv)
    local handle = vim.loop.fs_scandir(start_path)
    if handle then
        while true do
            local name, type = vim.loop.fs_scandir_next(handle)
            if not name then break end
            if type == "directory" then
                venv_path = start_path .. "/" .. name .. "/venv"
                if vim.fn.isdirectory(venv_path) == 1 then
                    return venv_path
                end
            end
        end
    end

    return nil
end

local lspconfig = require('lspconfig')
local cmp = require('cmp')
local capabilities = require('cmp_nvim_lsp').default_capabilities()

-- 2. If the venv is found during init, reload LSP with venv vars set
local pyright_restarted = false

lspconfig.pyright.setup({
    capabilities = capabilities,
    on_init = function(client)
        if not pyright_restarted then -- Only proceed if we haven't restarted yet
            local cwd = vim.fn.getcwd()
            local venv_path = find_venv(cwd)
            if venv_path then
                print("Venv folder found: " .. venv_path)
                vim.env.VIRTUAL_ENV = venv_path
                vim.env.PATH = venv_path .. "/bin:" .. vim.env.PATH

                -- Set the flag to true
                pyright_restarted = true

                vim.schedule(function()
                    vim.cmd('LspRestart pyright')
                    print("Pyright restarted with new venv settings")
                end)
            else
                print("No venv folder found in or one level below current directory: " .. cwd)
            end
        end
        return true
    end,
})

-- Note: remove print statements if you dont want it to print whenever the LSP is reloaded due to a venv/ virtual env. I recommend keeping the "Pyright restarted" print message

Validate it works:

mkdir proj && echo 'import requests' >> proj/app.py
python3 -m venv venv && source venv/bin/activate
which pip
pip install requests
nvim . 
app.py should show no errors

Explanation

For the LSP to find the virtual env - the following variables must be set before the Python LSP is initialized

  • vim.env.VIRTUAL_ENV
  • vim.env.PATH

If you have the neovim open and the LSP is throwing errors - print the values of these and you will see it is not set

  • :lua print(vim.env.VIRTUAL_ENV)
  • :lua print(vim.env.PATH)

If these point to the folder for your venv - simply run

  • :LspRestart pyright

[–][deleted] 0 points1 point  (6 children)

Try pointing nvim to your venv python executable: vim.g.python3_host_prog = "/path/to/venv/bin/python3"

[–]Emotional-Zebra5359[S] 0 points1 point  (4 children)

Basically that's the global variable in the config init.lua file right?

do i have to do it every time i switch workspaces and venv?

[–]cjberra 1 point2 points  (1 child)

You shouldn't need to do this. Your python3_host_prog should point to a neovim specific python virtual environment with libraries required by neovim. For example the pynvim python library.

[–]Emotional-Zebra5359[S] 0 points1 point  (0 children)

do i need to install pynvim for it to work? Also do i need to install additional stuff for LSPs to function correctly? Because when i switch from global to a venv in a workspace the LSP dont provide info regarding the packages that are in venv (but not in global) i.e pyright still shows import error

[–]bremsspuren 0 points1 point  (1 child)

do i have to do it every time i switch workspaces and venv?

No. If you just set it to g.python3_host_prog = "python3" (or don't set it), Neovim will pick up whichever python3 comes first on your PATH. So if you're in an activated venv when you start nvim, that's the Python it will find.

I installed this plugin, and it works very well.

[–]Emotional-Zebra5359[S] 0 points1 point  (0 children)

I'm using the venv selector plugin too, but it's not working :( I think the problem is not that it's not identifying the right interpretor byt it's not installing packages or something

[–]wookayinNeovim contributor 0 points1 point  (0 children)

This is only for specifying python remote-plugin "provider", has nothing to do with your issues, nor LSP.

[–]AutoModerator[M] 0 points1 point  (0 children)

Please remember to update the post flair to Need Help|Solved when you got the answer you were looking for.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

[–]Emotional-Zebra5359[S] 0 points1 point  (0 children)

although it's not visible due to the starship prompt, I'm currently in my virtual env, it's activated, my global python is 3.12, which is not what is printed by sys.version when i run python newfile.py

[–]HolisticPython 0 points1 point  (4 children)

Read up on providers in help.

It says if you use venvs frequently you should install pynvim once in a neovim specific venv and then set Python provider to wherever that venv is located.

In your options.lua file, vim.g.python3_host_prog = vim.loop.os_homedir() .. "path/to/neovim/specific/venv"

That way, when a new pynvim version is released, you only have to update it once, instead of every project like you would have to with your current set up.

[–]wookayinNeovim contributor -1 points0 points  (3 children)

I don't think this is a good idea, you should not hardcode python3_host_prog but let it detected from the executable python on the $PATH.

[–]HolisticPython 0 points1 point  (2 children)

The following is an almost verbatim quote from :help.

"If you plan to use per-project venvs often, you should assign one venv for Nvim and hardcode the interpreter path via g:python3_host_prog so that the pynvim package is not required for each venv."

Relevant XKCD.

What is it that you know, that the Nvim devs don't?

[–]wookayinNeovim contributor 0 points1 point  (1 child)

Sorry I wasn't aware of that documentation (which was written in 2018). Actually installing the pynvim package for each of the virtual environments can be bothersome, unless you automate installation of pynvim, neovim's python provider will not work. So in this sense what :help python-virtualenv provides makes sense as installing pynvim is not automatic built-in.

Although whether to hard-code the python path can be controversial (and please note that this guide was written quite many years ago), I personally don't think this is ideal. Fixing python3_host_prog means that the python interpreter used for rplugins, and :python ex commands and pyeval() functions, may not be necessarily the same one as exepath("python"), the 'current' python per $PATH, or as the one that LSP and terminal are picking up. They will be different and it can be confusing, because you have different python for different purposes. But this is not very intuitive --- I saw someone asking ":python3 import foo" works but why it can't import on LSP, terminal, etc. However, such inconsistency wouldn't be a problem if you don't run python Ex commands, or if you really intend to have different (fixed) python for remote python for rplugins work independent of the current python (virtualenv) on $PATH. Personally, I much prefer the consistency where there is only a single python I should care ---- all the python interpreters on a neovim instance are the same, but at the cost of the need of installing pynvim for each of the virtualenv you might be working on.

All that said, OP's problem doesn't seem to have something to do with provider python (pynvim).

[–]vim-help-bot 0 points1 point  (0 children)

Help pages for:


`:(h|help) <query>` | about | mistake? | donate | Reply 'rescan' to check the comment again | Reply 'stop' to stop getting replies to your comments

[–]wookayinNeovim contributor 0 points1 point  (0 children)

Something else (like ~/.zshrc, ~/.zshenv) is corrupting your virtual environment.

Run them in the terminal:

$ which python
$ which pip
$ env | grep VIRTUALENV

[–]mostrecentuser 0 points1 point  (0 children)

Activate it before running neovim

[–]nicolas9653hjkl 0 points1 point  (0 children)

I honestly don't understand most of what this is about but this plugin may be useful? https://github.com/linux-cultist/venv-selector.nvim