11

I do a lot of Python and I use almost all the time a virtualenv along with virtualenvwrapper to keep my modules organised.

But when I want to use those plugin from inside vim, through an external command, it seems that the shell is not aware of that config.

I need to have access to the virtualenv because

e.g.

(venv) $ python
>> import simple_history
>> # OK here

(venv) $ vim
:!python 
>> import simple_history
ImportError: No module named simple_history

My shell is shell=/bin/zsh, I guess I need to use this setting to access my virtualenv, but I can't figure out how...

1
15

I actually fixed this myself a long time ago. The problem is that when you run !python you're starting up a new shell with your existing environment. But, this means workon xxxx wasn't called to actually activate the virtualenv. This lead to a lot of confusion for me since $VIRTUAL_ENV was set.

I got around it by adding the following to my ~/.zshenv script:

if [[ -n $VIRTUAL_ENV && -e "${VIRTUAL_ENV}/bin/activate" ]]; then
  source "${VIRTUAL_ENV}/bin/activate"
fi

Since ~/.zshenv is sourced within the current session, it's a pretty safe assumption that the $VIRTUAL_ENV wasn't activated. Now when you run !python in Vim, it should use the virtualenv interpreter. You can confirm this by running :echo system('which python').

5
  • Oh this is nice, maybe it's not the place to ask the question, but why should your snippet be in .zshenv instead of .zshrc?
    – nobe4
    May 6 '16 at 6:17
  • 2
    @Nobe4 Because .zshrc is not always sourced, while .zshenv is guaranteed to be sourced. May 6 '16 at 7:52
  • Here is further information about the load order of zsh scripts: zsh.sourceforge.net/Intro/intro_3.html
    – Tommy A
    May 6 '16 at 13:36
  • 2
    I updated the answer because $ZSHENV_PATH_SET is irrelevant to solving the OP's problem. Adding the check for $VIRTUAL_ENV in that block was the result of late night troubleshooting.
    – Tommy A
    May 6 '16 at 13:51
  • 1
    to use with fish, i created ~/.config/fish/auto_source_venv.fish ` if test -e $VIRTUAL_ENV source $VIRTUAL_ENV/bin/activate.fish end ` and added . ~/.config/fish/auto_source_venv.fish to ~/.config/fish/config.fish
    – Tshirtman
    Nov 23 '19 at 16:12
0

For neovim and pyenv (also works for other python version managers that uses $VIRTUAL_ENV such as virtualenvwrapper) users with the same problem on nvim (venv not working properly, causing errors on checkhealth, lsp, pyright, etc), I know this is a little late, but since neovim checkhealth redirects to this question, I'm putting this answer here hoping it will help someone.

I created a function to autosource $VIRTUAL_ENV before calling nvim. This is a little different from Tommy A answer because venv is activated on the entire nvim env, so beyond solving !python it also solves :checkhealth, lsp and pyright problems.

Here is how I did with fish:

Create file ~/.config/fish/functions/nvimvenv.fish and save the content below in it:

# Autosource virtualenv; Workarround for nvim
function nvimvenv
  if test -e "$VIRTUAL_ENV"; and test -f "$VIRTUAL_ENV/bin/activate.fish"
    source "$VIRTUAL_ENV/bin/activate.fish"
    command nvim $argv # Run nvim program, ignore functions, builtins and aliases
    deactivate # Must deactivate on exit, otherwise venv will still be sourced which may cause undesirable effects on your terminal.
  else
    command nvim $argv # Run nvim program, ignore functions, builtins and aliases
  end
end;

There is no need to source it.

To use this function just open a new terminal and run nvimvenv, or you can set an alias to nvim by running alias nvim=nvimvenv on terminal and call it with nvim. If you want to make it permanent run with -s option like alias -s nvim=nvimvenv.

Here is the same function for bash and zsh (you will need to put/source this on your .bashrc or .zshrc):

function nvimvenv {
  if [[ -e "$VIRTUAL_ENV" && -f "$VIRTUAL_ENV/bin/activate" ]]; then
    source "$VIRTUAL_ENV/bin/activate"
    command nvim $@
    deactivate
  else
    command nvim $@
  fi
}

alias nvim=nvimvenv

PS: Also works for vim, just replace nvim for vim in the script, but if your concern is only running the right !python Tommy answer will be enough.

2
  • 1
    You can use command nvim in bash/zsh to force the shell to not use aliases/functions in that position. That avoids hard-coding /usr/bin/nvim, which may not be correct for everyone.
    – D. Ben Knoble
    Nov 16 '21 at 17:45
  • Didn't know about command, thank you Ben, this also works on fish. Edited. Nov 16 '21 at 17:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.