Pyenv: your Linux / Unix tool to manage different python versions

Huw Cordey/Minden Pictures

Installation

Install pyenv is relatively simple.

Mac OS

Consider using homebrew to install pyenv. The commands will be the following:

$ brew update
$ brew install pyenv

Linux / Unix

First be sure to have git installed. If it is not the case, use your favorite package manager and install it. Example for Debian family:

$ sudo apt-get install git
$ curl https://pyenv.run | bash

Configuration

If the previous command succeeded, you will see at the end of the output (the last six lines) something like the following:

# Load pyenv automatically by adding
# the following to ~/.bashrc:
export PATH="/home/ec2-user/.pyenv/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv virtualenv-init -)"
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(pyenv init --path)"' >> ~/.bashrc
$ echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrc
$ exec "$SHELL"
$ pyenv
pyenv 1.2.18
Usage: pyenv <command> [<args>]
Some useful pyenv commands are:
activate Activate virtual environment
commands List all available pyenv commands
...

Usage

Yeah now that we have pyenv installed, we want to install different python versions. The command install — list lists all available python versions handled by pyenv. It is an impressive list, and I discovered some distributions I didn’t know exist like activepython 😳

$ pyenv install --list
2.1.3
2.2.3
..

Mac OS

First be sure you have Xcode command line tools installed, if it is not the case run:

$ xcode-select --install
$ brew install openssl readline sqlite3 xz zlib

Debian family (debian, ubuntu, linux mint,..)

$ sudo apt-get update; sudo apt-get install --no-install-recommends make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev

Redhat family (Redhat, centos, Fedora before version 21)

$ sudo yum install gcc zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel tk-devel libffi-devel

Fedora 22 and above

$ dnf install make gcc zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel tk-devel libffi-devel
$ pyenv install 3.8.3
$ pyenv versions
* system (set by /home/ec2-user/.pyenv/version)
3.8.3
$ pyenv global 3.8.3
$ pyenv versions
system
* 3.8.3 (set by /home/ec2-user/.pyenv/version)
$ pyenv version
3.8.3 (set by /home/ec2-user/.pyenv/version)
$ python --version
Python 3.8.3
$ python
Python 3.8.3 (default, May 21 2020, 18:02:42)
[GCC 7.3.1 20180712 (Red Hat 7.3.1-6)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.version_info
sys.version_info(major=3, minor=8, micro=3, releaselevel='final', serial=0)
>>> exit()
$ pyenv install pypy3.6-7.3.1
$ pyenv versions
system
* 3.8.3 (set by /home/ec2-user/.pyenv/version)
pypy3.6-7.3.1
$ pyenv global pypy3.6-7.3.1
$ pyenv version
pypy3.6-7.3.1 (set by /home/ec2-user/.pyenv/version)
$ python --version
Python 3.6.9 (2ad108f17bdb, Apr 07 2020, 02:59:05)
[PyPy 7.3.1 with GCC 7.3.1 20180303 (Red Hat 7.3.1-5)]
$ python
Python 3.6.9 (2ad108f17bdb, Apr 07 2020, 02:59:05)
[PyPy 7.3.1 with GCC 7.3.1 20180303 (Red Hat 7.3.1-5)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.version
'3.6.9 (2ad108f17bdb, Apr 07 2020, 02:59:05)\n[PyPy 7.3.1 with GCC 7.3.1 20180303 (Red Hat 7.3.1-5)]'
>>> exit()

Managing different python versions per project

In case you have different projects on your computer (which is often the case), it is not practical to change the global python version every time you change a project. For this case there is the local command which comes in handy. It helps you define the python versions you need on a specific project. For example if I have a project running on python3.6, I can do this.

# before local command
# I installed python3.6 and python3.7 for this example
$ cd project
$ pyenv versions
system
3.6.10
3.7.7
3.8.3
* pypy3.6-7.3.1 (set by /home/ec2-user/.pyenv/version)
# after local command
$ pyenv local 3.6.10
$ pyenv versions
system
* 3.6.10 (set by /home/ec2-user/project/.python-version)
3.7.7
3.8.3
pypy3.6-7.3.1
$ pyenv local 3.6.10 3.7.7 3.8.3
$ pyenv versions
system
* 3.6.10 (set by /home/ec2-user/project/.python-version)
* 3.7.7 (set by /home/ec2-user/project/.python-version)
* 3.8.3 (set by /home/ec2-user/project/.python-version)
pypy3.6-7.3.1
$ cd ~
$ pyenv versions
system
3.6.10
3.7.7
3.8.3
* pypy3.6-7.3.1 (set by /home/ec2-user/.pyenv/version)

Python package isolation

Just be aware that activating local python versions for your project doesn’t mean that the packages you will install will be isolated per project. No! You will still need tools like virtualenv for that purpose. The latest versions of pyenv embed a plugin to facilitate virtualenv creation called pyenv-virtualenv. You can read the README to know how to use it. Personally, I prefer to use poetry which is elegant, simple and complete. And again I have a nice introduction here for those who are curious 😁

Other commands

You can update pyenv with update command. If there are changes, you will see ouput like the following:

$ pyenv update
Updating /home/ec2-user/.pyenv...
remote: Enumerating objects: 17, done.
remote: Counting objects: 100% (17/17), done.
remote: Compressing objects: 100% (8/8), done.
remote: Total 10 (delta 6), reused 1 (delta 1), pack-reused 0
Dépaquetage des objets: 100% (10/10), fait.
Depuis https://github.com/pyenv/pyenv
* branch master -> FETCH_HEAD
2c32a6b..cf81e5a master -> origin/master
Mise à jour 2c32a6b..cf81e5a
Fast-forward
README.md | 47 +++++++++++++++++++++++------------------------
plugins/python-build/share/python-build/stackless-3.7.5 | 2 +-
2 files changed, 24 insertions(+), 25 deletions(-)
$ pyenv uninstall 3.6.10
$ pyenv version
pypy3.6-7.3.1 (set by /home/ec2-user/.pyenv/version)
$ pyenv which pip3
/home/ec2-user/.pyenv/versions/pypy3.6-7.3.1/bin/pip3

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Kevin Tewouda

Kevin Tewouda

Déserteur camerounais résidant désormais en France. Passionné de programmation, sport, de cinéma et mangas. J’écris en français et en anglais dû à mes origines.