A collection of TILs, snippets and thoughts
<< Back to notes

Virtual environments and pyenv setup

Last updated

For years I've used virtualenv with virtualenvwrapper to manage virtual environments for python.

I've used this along side pyenv, which I use to manage multiple versions of python.

However, after updating pyenv to pyenv 2.0.0 my old approach of using mkvirtualenv and workon no longer worked.

I took the opportunity to review how I manage virtual environments and decided to use venv that comes package with python anyway.

Changes to bash_profile

I'm a mac user but I still haven't move over to zsh. I know I'll need to do this soon.

The first thing I had to do was remove the virtualenvwrapper setup stuff. The lines I removed were


Virtualenvwrapper setup

export WORKON_HOME=~/.virtualenvs source /usr/local/bin/ pyenv virtualenvwrapper_lazy ```

Then I update the lines that setup pyenv. The lines I have in my .bash_profile are

export PYENV_ROOT="$HOME/.pyenv" export PATH="$PYENV_ROOT/bin:$PATH" eval "$(pyenv init --path)"

Using virtual environments

To create a new virtual environment I use the pyenv virtualenv command. For example

pyenv virtualenv 3.8.6 my-virtual-env

where 3.8.6 is the version of python you want to use, and my-virtual-env is the name of the virtual environment.

The easiest way to use these virtual environments is to add a .python-version file to the root of the project where the virtual environment is required.

In the file add the name of the virtual environment. For example


Then, when you cd into the folder pyenv will automatically activate the environment. I no longer have to remember to activate it myself.

Updating the command prompt

I like to prepend the commandline prompt with the active virtual environment. That way I always know if I'm using one and can confidently install packages knowing I would accidently install them globally.

I found a way to do this in a comment on an issue in github. Huge thanks to the author keisuke-nakata.

Add the following to you .bash_profile file.

export PYENV_VIRTUALENVWRAPPER_PREFER_PYVENV="true" export PYENV_VIRTUALENV_DISABLE_PROMPT=1 export BASE_PROMPT=$PS1 function updatePrompt { PYENV_VER=$(pyenv version-name) # capture version name in variable if [[ "${PYENV_VER}" != "$(pyenv global | paste -sd ':' -)" ]]; then # MODIFIED: "system" -> "$(pyenv global | paste -sd ':' -)" export PS1="(${PYENV_VER%%:*}) "$BASE_PROMPT # grab text prior to first ':' character else export PS1=$BASE_PROMPT fi } export PROMPT_COMMAND="updatePrompt;$PROMPT_COMMAND"

Note the last line export PROMPT_COMMAND="updatePrompt;$PROMPT_COMMAND". If you have any other commands that update the commandline prompt (I have one that adds some git info such as the branch name) then make sure you include ;$PROMPT_COMMAND.

Originally, this tripped me up but worked as soon as I added that.

It works for me but any tips, do let me know.