pyenv Cheatsheet

·Updated April 13th, 2026

pyenv Cheatsheet

What is pyenv?

pyenv lets you switch between multiple Python versions on a per-user basis. It modifies your PATH at shell startup so that calls to python are intercepted and routed to the version you’ve selected — no sudo, no system-wide changes.

How pyenv resolves a Python version

pyenv checks the following sources in order, using the first match:

  1. PYENV_VERSION environment variable (if set)
  2. .python-version file in the current directory (walk up to /)
  3. ~/.pyenv/version (the global default)
  4. System Python as final fallback

Quick reference

TaskCommand
List installable versionspyenv install --list
Install a versionpyenv install 3.12.8
Set global defaultpyenv global 3.12.8
Set version for a projectpyenv local 3.11.10
Set version for current shellpyenv shell 3.13.1
Show active versionpyenv version
List installed versionspyenv versions
Uninstall a versionpyenv uninstall 3.10.15
Rehash shimspyenv rehash

Installation

1. Install build dependencies (openSUSE Tumbleweed)

Python versions are compiled from source, so you need a C toolchain and several libraries:

bash
sudo zypper install -y \
  gcc make automake \
  zlib-devel bzip2 libbz2-devel \
  readline-devel libffi-devel \
  libopenssl-devel libopenssl-1_1-devel \
  sqlite3-devel xz-devel lzma-sdk-devel \
  tk-devel ncurses-devel \
  patch git curl

Tip: If a zypper install fails for a specific package name, search with zypper se <keyword>. Tumbleweed renames packages occasionally during rolling updates.

2. Install pyenv via the official installer

bash
curl -fsSL https://pyenv.run | bash

This clones pyenv and useful plugins (pyenv-virtualenv, pyenv-update, pyenv-doctor) into ~/.pyenv.

Alternative: install via Git manually

bash
git clone https://github.com/pyenv/pyenv.git ~/.pyenv
cd ~/.pyenv && src/configure && make -C src   # optional, speeds up pyenv

3. Configure your shell

Add these lines to the end of your shell’s rc file.

Bash (~/.bashrc)

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

Zsh (~/.zshrc)

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

Fish (~/.config/fish/config.fish)

fish
set -gx PYENV_ROOT $HOME/.pyenv
fish_add_path $PYENV_ROOT/bin
pyenv init - fish | source
pyenv virtualenv-init - | source

After editing, restart your shell or exec $SHELL.

4. Verify the installation

bash
pyenv --version       # e.g. pyenv 2.5.x
pyenv doctor          # checks build deps

5. Updating pyenv

bash
pyenv update          # if installed via pyenv-installer
# or
cd ~/.pyenv && git pull   # if installed via git

6. Uninstalling pyenv

Remove the directory and the shell lines you added:

bash
rm -rf ~/.pyenv
# then delete the pyenv lines from ~/.bashrc / ~/.zshrc / config.fish

Core Commands

Installing Python versions

bash
# List every installable version (CPython, PyPy, Anaconda, etc.)
pyenv install --list

# Filter the list
pyenv install --list | grep '^\s*3\.12'

# Install a specific version
pyenv install 3.12.8

# Install with verbose output (useful for debugging build failures)
pyenv install -v 3.12.8

# Install with a custom build configuration
PYTHON_CONFIGURE_OPTS="--enable-optimizations --with-lto" pyenv install 3.12.8

Optimised builds: Adding --enable-optimizations --with-lto makes the build slower but produces a noticeably faster Python binary. Recommended for versions you use daily.

Selecting versions

pyenv global — user-wide default

bash
pyenv global 3.12.8            # single version
pyenv global 3.12.8 3.11.10    # fallback chain: try 3.12.8 first, then 3.11.10
pyenv global system             # revert to the system Python

Writes to ~/.pyenv/version.

pyenv local — per-project

bash
cd ~/projects/myapp
pyenv local 3.11.10

Creates a .python-version file in the current directory. Commit this file to your repo so collaborators get the same version.

pyenv shell — current terminal session only

bash
pyenv shell 3.13.1             # set
pyenv shell --unset             # clear

Sets the PYENV_VERSION env var. Highest priority, overrides local and global.

Inspecting state

bash
pyenv version                 # active version + where it was set
pyenv versions                # all installed versions (* marks active)
pyenv which python            # full path to the active python binary
pyenv whence pip              # which installed versions provide 'pip'
pyenv root                    # prints PYENV_ROOT (usually ~/.pyenv)
pyenv prefix 3.12.8           # prints the install prefix for a version

Uninstalling versions

bash
pyenv uninstall 3.10.15
pyenv uninstall -f 3.10.15    # skip confirmation prompt

Rehashing shims

pyenv uses shim executables in ~/.pyenv/shims/. If you install a new package that adds a CLI tool (e.g. pip install black), run:

bash
pyenv rehash

With pyenv init in your shell config, rehashing happens automatically most of the time. You only need this manually if a newly installed command is not found.

Multiple simultaneous versions

You can activate several versions at once. The first one listed becomes the default python, but executables unique to other versions remain accessible:

bash
pyenv global 3.12.8 3.11.10 3.10.15
python --version    # 3.12.8
python3.11 --version # 3.11.10
python3.10 --version # 3.10.15

This is handy for running tox or nox across multiple Python versions.


Virtual Environments

pyenv-virtualenv plugin

pyenv-virtualenv is installed automatically by the pyenv-installer. It lets you manage virtual environments as first-class pyenv versions.

Creating virtual environments

bash
# Create a virtualenv named "myproject" based on Python 3.12.8
pyenv virtualenv 3.12.8 myproject

# Create using the currently active Python version
pyenv virtualenv myproject

Virtual environments live inside ~/.pyenv/versions/ alongside regular Python installs.

Listing virtual environments

bash
pyenv virtualenvs

They also appear in pyenv versions — marked with the base version they were created from.

Activating / deactivating

Manual activation

bash
pyenv activate myproject
pyenv deactivate

Tie a virtualenv to a project directory with pyenv local:

bash
cd ~/projects/myapp
pyenv local myproject

If you added eval "$(pyenv virtualenv-init -)" to your shell config, the virtualenv activates and deactivates automatically when you cd in and out.

Deleting virtual environments

bash
pyenv virtualenv-delete myproject
# or equivalently
pyenv uninstall myproject

pyenv-virtualenv vs. plain venv

Featurepyenv-virtualenvpython -m venv
Managed by pyenv shimsYesNo
Auto-activate on cdYes (with virtualenv-init)No (needs manual source)
Lives in ~/.pyenv/versions/YesWherever you create it
Works with pyenv localYesNo

You can use both approaches. If you prefer python -m venv, pyenv still manages which Python version you’re calling — you just won’t get auto-activation via pyenv.

Typical project setup workflow

bash
# 1. Install the Python version you need
pyenv install 3.12.8

# 2. Create a virtualenv for your project
pyenv virtualenv 3.12.8 myapp-3.12

# 3. Bind it to your project folder
cd ~/projects/myapp
pyenv local myapp-3.12

# 4. Verify
python --version       # 3.12.8
which python           # ~/.pyenv/shims/python
pip install -r requirements.txt

Configuration & Environment Variables

Environment variables

VariablePurposeDefault
PYENV_ROOTWhere pyenv stores versions and shims~/.pyenv
PYENV_VERSIONOverride the active Python version(unset)
PYENV_SHELLShell type pyenv was initialized forauto-detected
PYENV_VIRTUALENV_DISABLE_PROMPTSet to 1 to stop virtualenv from modifying your prompt0
PYTHON_BUILD_MIRROR_URLCustom mirror for downloading source tarballs(python.org)
PYTHON_BUILD_CACHE_PATHCache directory for downloaded tarballs~/.pyenv/cache
PYTHON_BUILD_SKIP_MIRRORSet to 1 to skip mirrors entirely0

Build configuration flags

Pass these before pyenv install to customise the CPython build:

bash
# Optimised build (PGO + LTO)
PYTHON_CONFIGURE_OPTS="--enable-optimizations --with-lto" \
  pyenv install 3.12.8

# Enable shared library (needed by some embedding use-cases)
PYTHON_CONFIGURE_OPTS="--enable-shared" \
  pyenv install 3.12.8

# Custom OpenSSL path (useful if system OpenSSL is too old)
CPPFLAGS="-I/usr/local/opt/openssl/include" \
LDFLAGS="-L/usr/local/opt/openssl/lib" \
  pyenv install 3.12.8

# Parallel build (speed up compilation)
MAKE_OPTS="-j$(nproc)" pyenv install 3.12.8

Editor integration

VS Code

In .vscode/settings.json:

json
{
  "python.defaultInterpreterPath": "~/.pyenv/versions/<version>/bin/python"
}

Or let the Python extension detect pyenv automatically — it reads .python-version.

Neovim / LSP (pyright, pylsp)

Most LSP servers respect .python-version. Set pythonPath in your LSP config if auto-detection fails:

lua
require('lspconfig').pyright.setup {
  settings = {
    python = {
      pythonPath = vim.fn.expand("~/.pyenv/shims/python"),
    },
  },
}

CI integration

In GitHub Actions or similar, you usually don’t need pyenv — use the setup-python action instead. But if you do want pyenv in CI:

yaml
- name: Install pyenv
  run: |
    curl -fsSL https://pyenv.run | bash
    echo "$HOME/.pyenv/bin" >> $GITHUB_PATH
    echo "$HOME/.pyenv/shims" >> $GITHUB_PATH

- name: Install Python
  run: |
    pyenv install 3.12.8
    pyenv global 3.12.8

Useful aliases

Add to your ~/.bashrc or ~/.zshrc:

bash
alias pyls='pyenv versions'
alias pyuse='pyenv local'
alias pynew='pyenv virtualenv'
alias pydel='pyenv virtualenv-delete'

Troubleshooting

Build fails immediately

Symptom: pyenv install errors out before compilation starts.

Fix: Install the full build dependency set. On openSUSE Tumbleweed:

bash
sudo zypper install -y \
  gcc make automake \
  zlib-devel bzip2 libbz2-devel \
  readline-devel libffi-devel \
  libopenssl-devel sqlite3-devel \
  xz-devel tk-devel ncurses-devel \
  patch git curl

Run pyenv doctor to check what’s missing.

WARNING: No module named _ssl

Symptom: Python installs but pip or https requests fail.

Cause: OpenSSL headers were missing at build time.

Fix (openSUSE Tumbleweed):

bash
sudo zypper install libopenssl-devel libopenssl-1_1-devel
pyenv uninstall 3.12.8
pyenv install 3.12.8

For older Python versions (< 3.10) that need OpenSSL 1.1:

bash
sudo zypper install libopenssl-1_1-devel
CPPFLAGS="-I/usr/include/openssl-1_1" \
LDFLAGS="-L/usr/lib64/openssl-1_1" \
  pyenv install 3.9.20

ModuleNotFoundError: No module named '_lzma'

bash
sudo zypper install xz-devel lzma-sdk-devel
pyenv uninstall <version> && pyenv install <version>

ModuleNotFoundError: No module named '_sqlite3'

bash
sudo zypper install sqlite3-devel
pyenv uninstall <version> && pyenv install <version>

ModuleNotFoundError: No module named '_tkinter'

Only needed if you use tkinter (GUI):

bash
sudo zypper install tk-devel
pyenv uninstall <version> && pyenv install <version>

pyenv: command not found

Your shell config is missing the pyenv init lines, or you haven’t restarted the shell.

bash
# Verify pyenv is on PATH
ls ~/.pyenv/bin/pyenv

# Re-add to shell config (see Installation section), then:
exec $SHELL

Newly installed CLI tool not found (e.g. black, pytest)

After pip install <tool>, the shim may be stale:

bash
pyenv rehash

python resolves to system Python instead of pyenv’s

Check the resolution order:

bash
pyenv version          # what pyenv thinks is active
which python           # should be ~/.pyenv/shims/python
type python            # check for shell aliases/functions shadowing it

Common causes: a conda init block in your shell rc overriding PATH, or pyenv init placed before a conflicting PATH export.

Builds are slow

Use parallel make and consider skipping tests:

bash
MAKE_OPTS="-j$(nproc)" pyenv install 3.12.8

General debugging

bash
# Verbose install output — shows every compiler command
pyenv install -v 3.12.8

# Check pyenv health
pyenv doctor

# Print exact path to the active interpreter
pyenv which python

# Print the prefix directory
pyenv prefix