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 the separate name <entry>, packages
that install with save, then emits a python-build definition for it with
generate-installer. 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. Keeping the entry name
distinct from the version lets the binary sit alongside a normal source
install of the same version.
pyenv binary package 3.12.7:3.12.7-debian-12 \
--archive-base-url https://example.com/binaries
# writes 3.12.7-debian-12.tar.gz, its .meta file and
# a `3.12.7-debian-12' definition
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.