Back to Scaling Python Applications guides

How to Manage Multiple Python Versions With pyenv

Stanley Ulili
Updated on March 11, 2025

pyenv is a powerful tool for managing multiple Python versions on a single machine.

It allows you to easily switch between Python interpreters, ensuring compatibility across projects with varying requirements.

This article provides a detailed walkthrough of pyenv, demonstrating how to use it effectively to simplify your Python development workflow.

Prerequisites

Before exploring pyenv, you should be familiar with command-line operations. While you don't need to have Python pre-installed—pyenv can handle that for you—having some experience working with Python development environments will be beneficial.

Why use pyenv?

Before diving into pyenv, let's understand why managing multiple Python versions is essential for modern development workflows. Here's what makes pyenv particularly valuable:

  • Version isolation: Different projects often require different Python versions. While one might depend on Python 3.8 features, another might require Python 3.11's performance improvements.

  • Global vs. local interpreters: pyenv allows you to set both system-wide default Python versions and project-specific versions, providing flexibility without conflicts.

  • Seamless switching: Instead of manually installing and configuring multiple Python versions, pyenv handles the complexity of switching between interpreters with simple commands.

  • No sudo required: Unlike system-wide Python installations, pyenv installs versions in your user directory, eliminating permission issues and system conflicts.

Think of pyenv as a specialized tool that gives you complete control over your Python environment, making it easy to manage multiple projects with different requirements simultaneously.

Installing pyenv

In this section, you will install pyenv, the Python version manager that will allow you to easily switch between different Python interpreters.

Before installing pyenv, ensure you have the necessary build dependencies for compiling Python.

For Ubuntu/Debian:

 
sudo apt-get update
 
sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget curl llvm libncurses-dev \
xz-utils tk-dev libffi-dev liblzma-dev python3-openssl git

The most straightforward way to install pyenv is using the official installer script:

 
curl https://pyenv.run | bash

This will clone the pyenv repository to ~/.pyenv and set up the necessary shell integration. After installation, you must add pyenv to your shell configuration file.

For bash:

 
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
 
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
 
echo 'eval "$(pyenv init --path)"' >> ~/.bashrc
 
echo 'eval "$(pyenv init -)"' >> ~/.bashrc

After updating your shell configuration, restart your terminal or source the configuration file:

 
source ~/.bashrc

To verify that pyenv has been installed successfully, run:

 
pyenv --version
Output
pyenv 2.5.3

This output confirms that pyenv has been installed successfully and is ready to use.

Getting started with pyenv

Now that pyenv is installed, let's explore its core functionality. At its heart, pyenv manages multiple Python versions by manipulating your shell's PATH environment variable, ensuring the correct Python interpreter is used when you run python commands.

To see which Python versions are available for installation, run:

 
pyenv install --list

This will display a comprehensive list of Python versions that pyenv can install.

Output
Available versions:
  2.1.3
  2.2.3
  ...
  3.12.6
  3.12.7
  3.12.8
  3.12.9
  3.13.0
  3.13.0t
  3.13-dev
  3.13t-dev
  3.13.1
  3.13.1t
  3.13.2
  3.13.2t
  3.14.0a5
  3.14.0a5t
  3.14-dev
  3.14t-dev
  ...

To install a specific version, use:

 
pyenv install 3.13.2
Output
Downloading Python-3.13.2.tar.xz...
-> https://www.python.org/ftp/python/3.13.2/Python-3.13.2.tar.xz
Installing Python-3.13.2...

Installed Python-3.13.2 to /home/stanley/.pyenv/versions/3.13.2

You can install multiple Python versions:

 
pyenv install 3.12.9

To see which Python versions you have installed:

 
pyenv versions
Output
* system (set by /home/stanley/.pyenv/version)
  3.12.9
  3.13.2

The asterisk indicates the currently active Python version. By default, this is your system Python.

To switch to a different Python version globally:

 
pyenv global 3.12.9

This sets Python 3.12.2 as your default Python interpreter. Verify the change:

 
python3 --version
Output
Python 3.12.9
 
which python
Output
/home/stanley/.pyenv/shims/python

Notice that pyenv doesn't move Python binaries—instead, it creates shims that direct commands to the appropriate Python installation.

Let's create a simple script to verify our Python environment:

test.py
import sys
print(f"Using Python {sys.version}")
print(f"Located at {sys.executable}")

Run it to confirm the active Python version:

 
python test.py
Output
Using Python 3.12.9 (main, Mar 11 2025, 13:51:04) [GCC 13.3.0]
Located at /home/stanley/.pyenv/versions/3.12.9/bin/python

You've seen how pyenv simplifies Python version management by providing an interface to install, select, and manage multiple Python interpreters.

Instead of wrestling with system paths and package conflicts, pyenv gives you a clean, isolated environment for each Python version.

Working with project-specific Python versions

In the previous section, you learned how to install and set global Python versions with pyenv. While this works for system-wide settings, modern Python development often requires different Python versions for specific projects.

One of pyenv's most powerful features is its ability to set project-specific Python versions using the local command. This ensures that each project automatically uses the correct Python interpreter, without requiring manual switching.

To create a project directory with a specific Python version:

 
mkdir pyenv-demo && cd pyenv-demo

Set the local Python version for this project:

 
pyenv local  3.13.2

This creates a .python-version file in your project directory:

 
cat .python-version
Output
3.13.2

Now, whenever you enter this directory, pyenv automatically switches to Python 3.13.2:

 
python --version
Output
Python 3.13.2

Let's create another project that requires a different Python version.

Move out of the current directory:

 
cd ..

Create a new project directory and navigate into it:

 
mkdir legacy-project && cd legacy-project

Set a different Python version for this project:

 
pyenv local 3.12.9

Verify the Python version:

 
python --version
Output
Python 3.12.9

This project-level control ensures consistent environments across your team and prevents version conflicts between projects.

For temporary usage of a specific Python version, use the shell command:

 
pyenv shell 3.13.2
 
python --version
Output
Python 3.13.2

This sets the Python version only for your current shell session and precedes local and global settings.

To revert to the Python version specified by local or global settings:

 
pyenv shell --unset
 
python --version
Output
Python 3.12.9

Understanding pyenv's version precedence is essential:

  1. shell - Highest priority, set by pyenv shell
  2. local - Project-specific, set by pyenv local
  3. global - System-wide default, set by pyenv global

This hierarchy gives you granular control over which Python version is used in different contexts.

Integrating pyenv with virtual environments

While pyenv manages Python versions, virtual environments manage project dependencies. Combining these tools creates a great development workflow that ensures both interpreter and package consistency.

The pyenv-virtualenv plugin extends pyenv with virtual environment capabilities, bridging the gap between version management and dependency isolation.

First, let's return to our home directory from the legacy-project directory we were in:

 
cd ~

Now, install the plugin:

 
git clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv

If you see an error indicating the directory already exists, that's fine—it means the plugin is already installed.

Update your shell configuration to enable the plugin:

 
echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrc
 
source ~/.bashrc

Now you can create virtual environments tied to specific Python versions:

 
pyenv virtualenv 3.13.2 my-project-env

This creates a virtual environment named my-project-env using Python 3.13.2.

To activate this environment for a project. Create a new project directory and move into it:

 
mkdir enhanced-project && cd enhanced-project

Set the virtual environment for this project:

 
pyenv local my-project-env

Your shell prompt will update to show the active virtual environment. Install packages as usual:

 
pip install requests numpy pandas

These packages are installed only in the my-project-env environment, isolating your project dependencies.

To list your virtual environments:

 
pyenv virtualenvs
Output
  3.13.2/envs/my-project-env (created from /home/stanley/.pyenv/versions/3.13.2)
* my-project-env (created from /home/stanley/.pyenv/versions/3.13.2)

You can now move out of the directory:

 
cd ..

Combining pyenv with virtual environments creates a comprehensive solution for managing Python versions and project dependencies.

Managing development tools with pyenv

As your Python projects grow in complexity, you'll likely use various development tools like formatters, linters, and testing frameworks. pyenv can help manage these tools effectively, ensuring they're consistently available across projects.

One approach is to create a dedicated virtual environment for development tools.

First, create another directory and move into it:

 
mkdir dev-dir && cd dev-dir

Now create a new virtual environment:

 
pyenv virtualenv 3.13.2 dev-tools

Then activate this environment:

 
pyenv activate dev-tools

Install commonly used development tools in this environment:

 
pip install black pytest mypy flake8 isort

Now you can access these tools from any project by activating this environment. Set the shell to use this environment:

 
pyenv shell dev-tools

Verify that the tools are available by checking their version:

 
black --version
Output
black, 25.1.0 (compiled: yes)
Python (CPython) 3.13.2

Let's create a test directory to demonstrate project-specific tool configurations. First move out of the current directory:

 
cd ..

Create another project:

 
mkdir tool-test-project && cd tool-test-project

For project-specific tools, create a separate requirements file for development dependencies:

 
pip freeze > dev-requirements.txt

This approach keeps development tools separate from runtime dependencies, creating a cleaner and more organized workflow.

Another powerful feature of pyenv is the ability to use specific Python versions for individual commands with the pyenv exec command:

 
pyenv exec python -m pytest

This runs pytest using the currently active Python version, ensuring consistency between your development and testing environments.

This flexibility allows you to maintain consistent development practices across multiple projects, even when they require different Python versions.

Final thoughts

This article explored the key features of pyenv to help you manage multiple Python versions effectively. With pyenv, you can ensure consistent development environments across projects, teams, and deployment targets.

To explore the tool more thoroughly, check out the official documentation.

Thanks for reading!

Author's avatar
Article by
Stanley Ulili
Stanley Ulili is a technical educator at Better Stack based in Malawi. He specializes in backend development and has freelanced for platforms like DigitalOcean, LogRocket, and AppSignal. Stanley is passionate about making complex topics accessible to developers.
Got an article suggestion? Let us know
Next article
Introduction to PDM: A Python Project and Dependency Manager
Learn how to streamline your Python project management with PDM, a modern dependency manager that follows Python's latest standards. This comprehensive guide covers installation, dependency management, virtual environments, and Python version control, showing you how PDM provides a more efficient alternative to traditional tools like pip and virtualenv
Licensed under CC-BY-NC-SA

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Make your mark

Join the writer's program

Are you a developer and love writing and sharing your knowledge with the world? Join our guest writing program and get paid for writing amazing technical guides. We'll get them to the right readers that will appreciate them.

Write for us
Writer of the month
Marin Bezhanov
Marin is a software engineer and architect with a broad range of experience working...
Build on top of Better Stack

Write a script, app or project on top of Better Stack and share it with the world. Make a public repository and share it with us at our email.

community@betterstack.com

or submit a pull request and help us build better products for everyone.

See the full list of amazing projects on github