$linuxjunkies
>

Install Python with pyenv

Install pyenv on Linux to manage multiple Python versions safely alongside your distro Python, with build deps, version switching, and virtualenv setup.

BeginnerUbuntuDebianFedoraArch8 min readUpdated May 26, 2026

Before you start

  • A normal user account with sudo access
  • Internet access to download the installer and Python source tarballs
  • bash or zsh as your login shell

Your distro ships a system Python — and you should leave it alone. Package managers, system scripts, and tools like apt itself depend on it. pyenv lets you install any Python version side-by-side, switch between them per-project, and never touch the system interpreter. This guide walks from raw dependencies to a working virtual environment.

Why Not the Distro Python?

Debian 12 ships Python 3.11. Ubuntu 24.04 ships 3.12. Fedora 40 ships 3.12. None of those versions are necessarily what your project needs, and pip install into the system interpreter is a footgun — it can break OS tooling, and modern pip will refuse to do it without a virtual environment anyway. pyenv compiles Python from source into ~/.pyenv, completely isolated from /usr.

Install Build Dependencies

pyenv compiles CPython from source, so you need the toolchain and the development libraries Python's build system expects. Missing even one of these causes a silent partial build — you get Python, but without SSL, sqlite, or readline support.

Debian / Ubuntu

sudo apt update && sudo apt install -y \
  build-essential libssl-dev zlib1g-dev \
  libbz2-dev libreadline-dev libsqlite3-dev \
  libncursesw5-dev xz-utils tk-dev \
  libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev \
  curl git

Fedora / RHEL 9+ / Rocky Linux

sudo dnf install -y \
  gcc zlib-devel bzip2 bzip2-devel readline-devel \
  sqlite sqlite-devel openssl-devel tk-devel \
  libffi-devel xz-devel curl git

Arch Linux

sudo pacman -Sy --needed base-devel openssl zlib xz tk curl git

Install pyenv

The official installer script clones the pyenv repo and a handful of plugins into ~/.pyenv. Review the script at github.com/pyenv/pyenv-installer before running it if you prefer.

curl https://pyenv.run | bash

That installs pyenv itself plus pyenv-update and pyenv-virtualenv. Now wire it into your shell. Add these lines to the appropriate file~/.bashrc for Bash, ~/.zshrc for Zsh:

export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"

Reload your shell — don't just source the rc file, because pyenv init manipulates PATH in ways that compound if you source repeatedly:

exec "$SHELL"

Verify the install:

pyenv --version
# pyenv 2.x.x (version will vary)

Install a Python Version

List available CPython versions — the list is long, pipe it through grep:

pyenv install --list | grep -E '^  3\.(11|12|13)'

Install the version you want. This compiles from source and takes 2–5 minutes depending on hardware:

pyenv install 3.12.4

You can install multiple versions. They coexist without conflict:

pyenv install 3.11.9

List what you have installed:

pyenv versions
# * system (set by /home/user/.pyenv/version)
#   3.11.9
#   3.12.4

Set Python Versions

pyenv has three scopes for selecting a version, and they layer in priority order: shell > local > global.

Global (user-wide default)

Sets the fallback for any directory that doesn't have a .python-version file. The system interpreter stays untouched.

pyenv global 3.12.4

Local (per-project)

Run this inside your project directory. It writes a .python-version file that pyenv reads automatically when you cd into the directory.

cd ~/projects/myapp
pyenv local 3.11.9

Shell (current session only)

pyenv shell 3.12.4

Confirm which interpreter is active and where it lives:

python --version
pyenv which python
# /home/user/.pyenv/versions/3.12.4/bin/python

Create and Use Virtual Environments

pyenv-virtualenv wraps Python's built-in venv and hooks into pyenv's shim system, so your virtual environments activate automatically when you enter a directory.

Create a virtualenv

pyenv virtualenv 3.12.4 myapp-3.12

The name myapp-3.12 is arbitrary — use something that ties the environment to your project. The environment lives at ~/.pyenv/versions/myapp-3.12/.

Assign it to a project directory

cd ~/projects/myapp
pyenv local myapp-3.12

Now every time you enter that directory, pyenv activates myapp-3.12 automatically. You'll see the environment name in your prompt if your shell theme supports it. Install packages normally:

pip install requests flask

List and delete virtualenvs

pyenv virtualenvs
pyenv uninstall myapp-3.12

Keeping pyenv Updated

New Python releases need an updated pyenv to appear in pyenv install --list. The pyenv-update plugin makes this one command:

pyenv update

Verification

Run through this checklist after setup to confirm everything is wired correctly:

  1. Confirm the active interpreter is pyenv-managed, not /usr/bin/python3:
pyenv which python3
# Should show a path under ~/.pyenv/versions/...
  1. Confirm SSL works (many pip failures trace back to a broken OpenSSL build):
python -c "import ssl; print(ssl.OPENSSL_VERSION)"
  1. Confirm sqlite works:
python -c "import sqlite3; print(sqlite3.sqlite_version)"
  1. Confirm pip is scoped to your pyenv Python, not system:
pip --version
# pip X.Y.Z from /home/user/.pyenv/versions/...

Troubleshooting

pyenv: command not found after install

The shell init lines weren't picked up. Double-check they're in the right rc file for your shell (~/.bashrc vs ~/.zshrc vs ~/.profile for login shells), then run exec "$SHELL" again. If you're on a login shell (common with SSH), you may need to add the lines to ~/.bash_profile instead.

Build fails with ERROR: The Python ssl extension was not compiled

The OpenSSL development headers were missing or the wrong version. On RHEL-family systems, also try installing openssl11-devel if your version of RHEL ships OpenSSL 1.x. Reinstall the build deps, then re-run pyenv install.

python still points to /usr/bin/python3

Run echo $PATH and confirm ~/.pyenv/shims and ~/.pyenv/bin appear before /usr/bin. If not, the export PATH line in your rc file isn't being sourced, or it was placed after another tool that resets PATH.

Slow cd with virtualenv auto-activation

The pyenv virtualenv-init - hook adds a small check on every directory change. If it's perceptibly slow, consider activating environments manually with pyenv activate myenv and removing the virtualenv-init line from your rc file.

tested on:Ubuntu 24.04Debian 12Fedora 40Arch rolling

Frequently asked questions

Is it safe to run pyenv alongside the system Python?
Yes. pyenv installs entirely into ~/.pyenv and uses shims to intercept the python and pip commands. It never modifies /usr/bin/python3 or any system path, so OS tooling is unaffected.
Do I need sudo to use pyenv?
No. Everything lives under your home directory. sudo is only required when installing the build dependencies with your package manager.
How is pyenv different from using python3 -m venv directly?
venv creates isolated package environments but always uses the Python version it was invoked with. pyenv lets you install and switch between different CPython releases entirely, then optionally layer venv-style isolation on top via pyenv-virtualenv.
Can I use pyenv in CI pipelines or Docker containers?
You can, but it's usually overkill. Docker images can pin a specific Python base image, and most CI systems offer direct Python version selection. pyenv shines on developer workstations where multiple projects need different versions.
How do I completely remove pyenv?
Remove the shell init lines from your rc file, then delete the ~/.pyenv directory. That's it — no system files were touched.

Related guides