The go-to resource for upgrading Python, Django, Flask, and your dependencies.

asdf Python Plugin: Installing Multiple Python Versions on Ubuntu 24.04 LTS


When we work on Python projects, we often encounter the need for different versions—perhaps 3.12 for current development, 3.10 for maintaining legacy code, or even older releases for specific compatibility. Ubuntu 24.04 provides Python 3.12 by default, which covers many situations. For other versions, though, we have choices: the deadsnakes PPA offers pre-built Debian packages; pyenv builds Python from source with a focus on the language alone; asdf-vm manages versions across languages through plugins.

asdf originated as a Haskell version manager and evolved into a general tool with community plugins for Python, Node.js, Ruby, and more. Pyenv suits Python-centric workflows well. asdf, however, provides consistency across languages via shims and .tool-versions files. In this guide, we’ll install asdf and the Python plugin on Ubuntu 24.04 LTS (Noble Numbat). We’ll cover prerequisites, installation steps, version management, and common issues—tested on fresh systems.

We’ll use asdf here for its extensibility, but you can adapt these steps to pyenv if your needs are Python-only.

Why asdf-vm?

Pyenv focuses on Python, with shims and per-project .python-version files. Other languages need separate tools.

Deadsnakes PPA offers apt integration but follows Ubuntu timelines—newest Python versions delay.

asdf-vm’s plugin model lets communities define install logic per language. Shims dynamically select versions based on .tool-versions hierarchy.

asdf requires build deps like pyenv but unifies workflows. For Python-only, pyenv avoids overhead.

Multi-language projects benefit from asdf’s consistency.

Prerequisites: Install Build Dependencies

Python builds from source, so install Ubuntu 24.04 dependencies first:

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

These packages provide compilers (build-essential, make), SSL (libssl-dev), compression (zlib1g-dev, libbz2-dev, liblzma-dev), readline for interactive shell (libreadline-dev), SQLite (libsqlite3-dev), XML (libxml2-dev, libxmlsec1-dev), FFI (libffi-dev), terminal/GUI (libncursesw5-dev, tk-dev), downloaders (wget, curl), and git. Missing ones cause configure errors during Python builds.

Step 1: Install asdf-vm Core

Clone the latest stable:

$ git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.1

Add to ~/.bashrc (or ~/.zshrc for Zsh):

$ echo '. $HOME/.asdf/asdf.sh' >> ~/.bashrc
$ echo 'export PATH="$HOME/.asdf/shims:$PATH"' >> ~/.bashrc

Reload:

$ source ~/.bashrc

Verify:

$ asdf --version

asdf 0.14.1


## Step 2: Add Python Plugin

```bash
$ asdf plugin add python https://github.com/asdf-community/asdf-python.git

List available versions:

$ asdf list all python | head -20

3.13.0rc1 3.13.0b1 3.12.7 3.12.6 …


## Step 3: Install Multiple Python Versions

Install latest stable (e.g., 3.12.x), 3.11, and 3.10:

```bash
$ asdf install python latest
$ asdf install python 3.11.9
$ asdf install python 3.10.14

(Each build takes 5-15 minutes depending on hardware.)


Builds take 5-15 minutes each. Use `asdf install python ref:3.12.3` for exact commits if needed.

## Step 4: Set Global or Local Versions

**Global** (system-wide default):

```bash
$ asdf global python 3.12.3

Project-local (creates .tool-versions):

$ mkdir myproject
$ cd myproject
$ asdf local python 3.11.9

Creates .tool-versions with python 3.11.9.


For multiple versions (e.g., fallback for scripts):

```bash
$ asdf global python 3.12.3 3.11.9

python uses 3.12.3; if unavailable, falls to 3.11.9.

Verify Installation

$ python --version
Python 3.12.3
$ asdf current
python    3.12.3  (global)
$ pip --version
pip 24.2 from ... (python 3.12)

Switch directories—local .tool-versions overrides global.

Reshim for Pip Binaries

After pip install ipython, run:

$ asdf reshim python

(Generates shims for pip-installed tools like ipython.)


Adds shims for `ipython`.

## Troubleshooting Common Issues on Ubuntu 24.04

Build failures often stem from missing deps—double-check the list.

- **SSL/OpenSSL errors**: Install `libssl-dev`; Ubuntu 24.04 uses OpenSSL 3—some older Python may need patches.
- **Missing headers (e.g., ffi.h, readline.h)**: Verify `libffi-dev`, `libreadline-dev`.
- **Out of memory during compile**: Use machine with more RAM or build one version at a time.
- **Permission denied in ~/.asdf**: `chmod -R u+rwX ~/.asdf`.
- **Zsh/Fish users**: Add to respective rc files instead of .bashrc.
- **pip not found after install**: Run `asdf reshim python $(asdf current python)`.

Shims prevent system Python conflicts by prepending ~/.asdf/shims.

For more, check [asdf-python issues](https://github.com/asdf-community/asdf-python/issues).

## Conclusion

asdf's Python plugin provides a reliable way to handle multiple versions on Ubuntu 24.04 LTS. .tool-versions files enable reproducible setups across machines and teams, supporting long-term maintenance.

Consider asdf plugins for Node.js, Ruby, or others in polyglot projects.

**Key takeaways:**
- Prereqs → clone asdf → plugin add → install versions → global/local.
- Commands: `asdf list all python`, `install`, `global/local`, `current`, `reshim`.
- Shims route commands to correct versions transparently.

Found issues? Comment below or check [deadsnakes PPA](https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa) for pre-built alternatives.

Sponsored by Durable Programming

Need help maintaining or upgrading your Python application? Durable Programming specializes in keeping Python apps secure, performant, and up-to-date.

Hire Durable Programming