When you boot up a new machine, it will usually come preinstalled with a version of Python. You can verify this by running the following:
# This shows the version installed. $ python -V Python 2.7.18 # This shows the location of the installation. $ which python /usr/bin/python
That’s great, but do not use “System Python.” It came with your operating system because it is a dependency that should not be tampered with. Doing so could harm your system or the very least, cause you a lot of grief down the road.
You could work around this by manually installing other versions of Python, but that is hard to manage and can get messy fast, especially if you have multiple projects depending on different versions of Python.
Instead of dealing with all that, you might want to invest of few minutes setting up a Python Version Manager, in this case,
pyenv, that will let you easily switch between multiple versions of Python.
If that sounds good to you, continue reading to learn how to install and use
I’m not going to get super specific on the installation of
pyenv because it depends on the machine you are working with. These instructions are what got me set up on my specific machine (M1 Mac using Zsh), so your mileage may vary. Here are the official instructions if these don’t work for you.
- homebrew, the missing package manager for macOS.
- pyenv, the python version manager.
- pyenv-virtualenv, a virtualenv plugin for
Before you can install
pyenv, you need to install all its dependencies.
# Install Xcode Command Line Tools xcode-select --install # Install Homebrew /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" echo 'export PATH=/opt/homebrew/bin:$PATH' >> ~/.zshrc # Install Python build dependencies brew install openssl readline sqlite3 xz zlib
Now we can install
brew and configure your terminal to let
pyenv dictate which version of Python you are using.
# Install pyenv brew install pyenv pyenv-virtualenv # Configure shell environment echo 'eval "$(pyenv init --path)"' >> ~/.zshrc echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.zshrc echo 'if which pyenv-virtualenv-init > /dev/null; then eval "$(pyenv virtualenv-init -)"; fi' >> ~/.zprofile
You know you’ve set everything up correctly if you see the following:
# You've installed pyenv! $ pyenv --version pyenv 2.2.4 # pyenv put itself between your system and terminal! # Notice that the installation path is different now. $ which python /Users/<user>/.pyenv/shims/python
pyenv installed, we can do some powerful stuff!
- Install pretty much whatever version of Python we want.
- Create virtualenvs that act like separate Python installations.
- Set the global, local, and shell versions of Python we want to use.
How It Works
pyenv will use “System Python,” which as I mentioned we shouldn’t use, so we need to install other versions. When you install a new version of Python using
pyenv, it stores them in its root directory (
After we install the versions of Python we want, we need to tell
pyenv where and when we want to use each version by using the
- When we use the
globalcommand, we are setting the global Python version.
pyenvrecords this information in this file
- When we use the
localcommand, we are setting the local application-specific Python version. This will apply to all its subdirectories as well!
pyenvrecords this information by creating a file in the current directory called
- When we use the
shellcommand, we are setting the shell-specific Python version.
pyenvrecords this information by setting the
So how does
pyenv decide which version to use?
As we move between directories
pyenv searches for the files and environment variable we set above and processes them in the following order:
$PYENV_VERSION. This version will be used if set.
.python-version. This version will be used if this file exists.
~/.pyenv/version. This version will be used if this file exists.
- If none of these exist, it will use “System Python”.
What about virtualenvs?
Working with virtualenvs is extremely simple. All we have to do is use the
virtualenv command and specify the version of Python we want to use.
pyenv then creates the virtualenv it’s root directory which we can use with the
shell commands, just like the full Python installations!
And if you configured your shell correctly, you don’t even have to run any
pyenv will handle that when you enter and leave directories.
Now that you have a basic understanding of how
pyenv works, here is an overview of its available commands.
Install a Python version using python-build.
pyenv builds each installation from source, so it could be a few seconds for this command to complete.
$ pyenv install 3.10.2
Uninstall a specific Python version.
$ pyenv uninstall 3.10.2
List all Python versions available to pyenv.
$ pyenv versions system * 3.10.2 (set by /Users/<user>/.pyenv/version)
Notice that there is a
* indicating what is the active version of Python and it tells you how
pyenv decided to use that version.
Set or show the global Python version.
$ pyenv global system $ pyenv global 3.10.2 $ pyenv global 3.10.2 $ python -V Python 3.10.2
This will update the
Set or show the local application-specific Python version.
$ pyenv local pyenv: no local version configured for this directory $ pyenv local 3.10.2 $ pyenv local 3.10.2 $ python -V Python 3.10.2
This will create or update the
.python-version file in the current directory.
Set or show the shell-specific Python version.
$ pyenv shell pyenv: no shell-specific version configured $ pyenv shell 3.10.2 $ pyenv shell 3.10.2 $ python -V Python 3.10.2
This will set the
$PYENV_VERSION environment variable.
Creates a Python virtualenv in the
pyenv root directory.
$ pyenv virtualenv [version] <name>
If no version number is given, the current active version will be used. You can name the virtualenv whatever you want, but it is best practice to name it the same as the relevant project.
Uninstall a specific Python virtualenv.
$ pyenv virtualenv-delete <name>
List all Python virtualenvs.
$ pyenv virtualenv project $ pyenv virtualenvs 3.10.2/envs/project (created from /Users/<user>/.pyenv/versions/3.10.2) project (created from /Users/<user>/.pyenv/versions/3.10.2)
You will see two entries per virutalenv (
pyenv versions does the same thing). In this example,
3.10.2/envs/project is the actual virtualenv and
project is a shorthand simlink to that folder.
Once a vitualenv is created, we can use it along with the
$ pyenv local project $ pyenv local project
I hope by reading this post you see how useful having a version manager like
pyenv can be and were able to get up and running quickly. I know I sure have!
If you have any feedback, click the button below. I’d love to hear from you!