Managing Multiple Python Versions With pyenv

pyenv is a tool for managing multiple Python versions. Even if you already have Python installed on your system, it worth to have pyenv installed so that you can easily try out new language features or help contribute to a project that is on a different version of Python. So, let’s review the reasoning to manage different Python versions easily and flexibly:

  • Install Python in your user space
  • Install multiple versions of Python
  • Specify the exact Python version you want
  • Switch between the installed versions
  • pyenv lets you do all of these things and more.

Using pyenv to Install Python

Now that you have pyenv installed, installing Python is the next step. You have many versions of Python to choose from. If you wanted to see all the available CPython 3.6 through 3.8, you can do this:

$ pyenv install --list | grep " 3\.[678]"

Once you find the version you want, you can install it with a single command:

pyenv install -v 3.7.2

Installation Location

As mentioned before, pyenv works by building Python from source. Each version that you have installed is located nicely in your pyenv root directory:

$ ls ~/.pyenv/versions/

All of your versions will be located here. This is handy because removing these versions is trivial:

$ rm -rf ~/.pyenv/versions/2.7.15

Of course pyenv also provides a command to uninstall a particular Python version:

$ pyenv uninstall 2.7.15

Using Your New Python

Now that you’ve installed a couple of different Python versions, let’s see some basics on how to use them. First, check what versions of Python you have available:

$ pyenv versions

The * indicates that the system Python version is active currently. You’ll also notice that this is set by a file in your root pyenv directory. This means that, by default, you are still using your system Python:

$ python -V

If you try to confirm this using which, you’ll see this:

$ which python

This might be surprising, but this is how pyenv works. pyenv inserts itself into your PATH and from your OS’s perspective is the executable that is getting called. If you want to see the actual path, you can run the following:

$ pyenv which python

If, for example, you wanted to use version 2.7.15, then you can use the global command:

$ pyenv global 2.7.15
$ python -V
$ pyenv versions

pyenv Commands

pyenv offers many commands. You can see a complete list of all available commands with this:

$ pyenv commands

This outputs all command names. Each command has a –help flag that will give you more detailed information. For example, if you wanted to see more information on the shims command you could run the following:

$ pyenv shims --help

The help message describes what the command is used for and any options you can use in conjunction with the command. In the following sections, you’ll find a quick, high-level overview of the most used commands.

install

You’ve already seen the install command above. This command can be used to install a specific version of Python. For example, if you wanted to install 3.6.8 you would use this:

$ pyenv install 3.6.8

The output shows us pyenv downloading and installing Python. Some of the common flags you may want to use are the following:

Flag Description -l/–list Lists all available Python versions for installation -g/–debug Builds a debug version of Python -v/–verbose Verbose mode: print compilation status to stdout

versions

The versions command displays all currently installed Python versions:

$ pyenv versions

This output shows not only that 2.7.15, 3.6.8, 3.8-dev, and your system Python are installed, but also shows you that the system Python is active. If you only care about the current active version, you can use the following command:

$ pyenv version

This command is similar to versions but only shows you the current active Python version.

which

The which command is helpful for determining the full path to a system executable. Because pyenv works by using shims, this command allows you to see the full path to the executable pyenv is running. For example, if you wanted to see where pip is installed, you could run this:

$ pyenv which pip

The output displays the full system path for pip. This can be helpful when you’ve installed command-line applications.

global

The global command sets the global Python version. This can be overridden with other commands, but is useful for ensuring you use a particular Python version by default. If you wanted to use 3.6.8 by default, then you could run this:

$ pyenv global 3.6.8

This command sets the ~/.pyenv/version to 3.6.8. For more information, see the section on specifying your Python version.

local

The local command is often used to set an application-specific Python version. You could use it to set the version to 2.7.15:

$ pyenv local 2.7.15

This command creates a .python-version file in your current directory. If you have pyenv active in your environment, this file will automatically activate this version for you.

shell

The shell command is used to set a shell-specific Python version. For example, if you wanted to test out the 3.8-dev version of Python, you can do this:

$ pyenv shell 3.8-dev

This command activates the version specified by setting the PYENV_VERSION environment variable. This command overwrites any applications or global settings you may have. If you want to deactivate the version, you can use the –unset flag.

pyenv and Virtual Environments

What is important to know:

  • pyenv manages multiple versions of Python itself.
  • virtualenv/venv manages virtual environments for a specific Python version.
  • pyenv-virtualenv manages virtual environments for across varying versions of Python.

Creating Virtual Environments

$ pyenv virtualenv <python_version> <environment_name>

$ pyenv virtualenv 3.6.8 myproject

Activating your Environment

$ pyenv local myproject

This command a .python-version file in your current working directory and because you ran eval $(pyenv virtualenv-init -) in your environment, the environment will automatically be activated. You can verify this by running the following:

$ pyenv which python
/home/foss/.pyenv/versions/myproject/bin/python

Another way to manually activate/deactivate your Python environment is:

$ pyenv activate <environment_name>
$ pyenv deactivate

Working With Multiple Environments

If there is the need to work with two different projects:

  • project1 supports Python 2.7 and 3.6.
  • project2 supports Python 3.6 and experiments with 3.8-dev.

First, create a virtual environment for project1:

$ cd project1/
$ pyenv which python
/usr/bin/python
$ pyenv virtualenv 3.6.8 project1
...
$ pyenv local project1
$ python -V
/home/foss/.pyenv/versions/project1/bin/python

When you leave the project folder you are back to the default Python version:

$ cd $HOME
$ pyenv which python
/usr/bin/python

Now create a virtual environment for project2:

$ cd project2/
$ pyenv which python
/usr/bin/python
$ pyenv virtualenv 3.8-dev project2
...
$ pyenv local 3.8-dev
$ pyenv which python
/home/foss/.pyenv/versions/3.8-dev/bin/python

These are one time steps for your projects. Now, as you cd between the projects, your environments will automatically activate:

Now you can switch between your projects and pyenv will take care of automatically activating the correct Python versions and the correct virtual environments.

Activating Multiple Versions Simultaneously

As described in the example above, project2 uses experimental features in 3.8. Suppose you wanted to ensure that your code still works on Python 3.6. If you try running python3.6, you’ll get this:

$ cd project2/
$ python3.6 -V
pyenv: python3.6: command not found

The `python3.6' command exists in these Python versions:
  3.6.8
  3.6.8/envs/project1
  project1

pyenv tells you that, while Python 3.6 is not available in the current active environment, it is present in other environments. pyenv gives you a way to activate multiple environments:

$ pyenv local project2 3.6.8

That indicates to pyenv to use the virtual environment project2 as the first option. So if a command, for example python, can be resolved in both environments, it will pick project2 before 3.6.8:

$ python3.6 -V
Python 3.6.8

Here, pyenv attempts to find the python3.6 command, and because it finds it in an environment that is active, it allows the command to execute. This is extremely useful for tools like tox that require multiple versions of Python to be available on your PATH in order to execute.

Suppose that in the above example, you’ve found a compatibility problem with your library and would like to do some local testing. The testing requires that you install all the dependencies. You should follow the steps to create a new environment:

$ pyenv virtualenv 3.6.8 project2-tmp
$ pyenv local project2-tmp

Once you’re satisfied with your local testing, you can easily switch back to your default environment:

$ pyenv local project2 3.6.8