3.5 KiB

pyenv-binary (experimental)

Package an installed Python version into a relocatable archive that can be installed on another machine.

This is experimental and intentionally decoupled: it does not change pyenv install or any other command. You drive it explicitly through pyenv binary. Run pyenv binary <command> --help for details on a command.

Portability

An archive is portable across machines that share its build platform (OS, architecture and a compatible libc) and have the recorded system libraries. It is not portable across, say, glibc and musl, or to an older glibc; the platform and dependency metadata exist to catch that.

Commands

pyenv binary package <version>[:<entry>] --archive-base-url <url>

Installs <version> from source under a separate name, packages that install with save, then emits a python-build definition for it with generate-installer. With no explicit entry, the name is generated from the current platform, platform version and architecture. An explicit entry keeps the existing custom-build workflow.

pyenv binary package 3.12.7 \
  --archive-base-url https://example.com/binaries
# On Debian 12 x86_64, writes 3.12.7-debian-12-x86_64.tar.gz,
# its .meta file and a `3.12.7-debian-12-x86_64' definition.

pyenv binary package 3.12.7:company-python \
  --archive-base-url https://example.com/binaries

The archive, metadata and definition land in the current directory, named after the entry. Host the archive under <url> and drop the definition into python-build's definition directory.

pyenv binary package-name <version>

Prints the automatically generated entry name without building anything. Linux uses the distribution name and version, macOS uses the macOS version, and other systems use the name and release reported by uname. All names include the architecture.

pyenv binary package-name 3.12.7
# 3.12.7-debian-12-x86_64

pyenv binary save <version> [<output-dir>] [--name <name>]

Packs an installed version into <version>-<platform>.tar.gz (relative paths) and writes <version>-<platform>.meta describing the build platform (OS, arch, distro and libc version) and the system libraries the build links against. Use --name to set a different base name for both files.

pyenv binary save 3.12.7 ./dist

pyenv binary generate-installer <metadata-file> --archive-url <url> [-o <output>]

Reads a .meta file and emits a python-build definition. Drop it into python-build's definition directory and pyenv install <name> installs the archive like any other version. The archive location is a parameter, so you can host it anywhere (it does not have to be a pyenv location); the archive itself must sit next to the .meta file so its checksum can be baked into the definition.

The definition refuses to install on a different OS/architecture, or an older glibc, than the archive was built for, and checks that the system libraries it needs are present.

pyenv binary generate-installer ./dist/3.12.7-linux-x86_64.meta \
  --archive-url https://example.com/3.12.7-linux-x86_64.tar.gz \
  -o "$(pyenv root)/plugins/python-build/share/python-build/3.12.7-linux-x86_64"

pyenv install 3.12.7-linux-x86_64

pyenv binary relocate <prefix>

Rewrites the rpaths of a Python tree unpacked into <prefix> so the interpreter and its extension modules load the bundled libraries from there rather than from the path the archive was built at. Uses patchelf. The generated definition calls this; you rarely run it by hand.

Relocation is implemented for Linux; macOS is not wired up yet.