Skip to main content

Portable python binaries

Version on pypi Tested with Github Actions Test coverage Python versions tested (link to github project)

Portable-Python is a CLI (and a python library) for compiling python binaries from source than can be decompressed in any folder, and used from there without further ado (ie: no need to run an “installer”).

Motivation

The idea here is to allow for automated systems to:

  • Easily obtain a python binary, that can be used in sandboxes / workstations / laptops / instances…

  • Inspect any python installation, and point out how portable it is, which shared or non-standard libraries it is using

Installation

portable-python is a regular python CLI, it can be installed with:

pickley:

pickley install portable-python
portable-python --help
portable-python inspect /usr/bin/python3

Or pipx:

pipx install portable-python
portable-python inspect /usr/bin/python3

Using pip install (a CI builder would probably do this):

/usr/bin/python3 -mvenv /tmp/pp
/tmp/pp/bin/python -mpip install portable-python
/tmp/pp/bin/portable-python --help
/tmp/pp/bin/portable-python inspect /usr/bin/python3

Supported operating systems

Portable python binaries can be built for Linux and MacOS (Intel/M1/M2).

Currently Windows is NOT supported, contributions are welcome.

Python binaries can be produced as “portable” (statically linked, can run from any folder where the binary is unpacked in), or with a --prefix (build targeted to live in a pre-determined folder, like /apps/pythonM.m)

Operating system

Portable

–prefix

Linux

✅

✅

Macos

✅

✅

Windows

❌

❌

Building a portable cpython

Once portable-python is installed:

Build a binary:

cd some-temp-folder
portable-python build 3.9.7
ls -l dist/cpython-3.9.7-macos-arm64.tar.gz

Unpack it somewhere:

tar -C ~/tmp/versions/ -xf dist/cpython-3.9.7-macos-arm64.tar.gz
ls -l ~/tmp/versions/

It’s ready to be used:

~/tmp/versions/3.9.7/bin/python --version

Note that you can use --dryrun mode to inspect what would be done without doing it:

$ portable-python --dryrun build 3.9.7

INFO selected: xz openssl gdbm (3 modules) xz:5.2.5 openssl:1.1.1k gdbm:1.18.1
INFO Platform: macos-x86_64
...
--------------
-- xz:5.2.5 --
--------------
Would download https://tukaani.org/xz/xz-5.2.5.tar.gz
Would untar build/sources/xz-5.2.5.tar.gz -> build/components/xz
INFO env PATH=build/deps/bin:/usr/bin:/bin
INFO env MACOSX_DEPLOYMENT_TARGET=10.14
Would run: ./configure --prefix=build/deps --enable-shared=no --enable-static=yes ...
...
-------------------
-- cpython:3.9.7 --
-------------------
Would download https://www.python.org/ftp/python/3.9.7/Python-3.9.7.tar.xz
Would untar build/sources/Python-3.9.7.tar.xz -> build/components/cpython
...
Would run: ./configure --prefix=/ppp-marker/3.9.7 --enable-optimizations ...
Would run: /usr/bin/make
Would run: /usr/bin/make install DESTDIR=build
...
Would tar build/3.9.7 -> dist/cpython-3.9.7-macos-x86_64.tar.gz

CLI reference

Main entry point:

portable-python [OPTIONS] COMMAND [ARGS]

Global options:

  • --config PATH: Config file (default: portable-python.yml)

  • --quiet: Turn off DEBUG logging

  • --dryrun / -n: Show what would be done

  • --target PLATFORM: Override detected platform (for testing)

build <PYTHON_SPEC> - Build a portable Python binary:

portable-python build 3.13.2 -m openssl,zlib
  • --modules, -m CSV: External modules to include

  • --prefix, -p PATH: Use --prefix (non-portable)

build-report [PYTHON_SPEC] - Show module status and what will be compiled:

  • --modules, -m CSV: Specific modules to check

  • Validates that modules can be built

inspect <PATH> - Check if a Python installation is portable:

portable-python inspect /usr/bin/python3
  • --modules, -m MODULES: Which modules to inspect

  • --verbose, -v: Show full .so report

  • --prefix, -p: Built with --prefix (not portable)

  • --skip-so, -s: Don’t check all .so files

list [FAMILY] - List available versions (default: cpython):

portable-python list cpython
  • --json: Output as JSON

diagnostics - Show system diagnostics

recompress <PATH> <EXT> - Re-compress existing binary tarball (for comparing compression sizes)

lib-auto-correct <PATH> - Auto-correct exes/libs to use relative paths:

  • --commit: Actually perform changes (dryrun by default)

  • --prefix, -p PATH: Expected --prefix from build

Library

Portable Python can be used as a python library to invoke builds, or inspect an installation.

Invoke a build from python code:

from portable_python import BuildSetup, required_python_spec

setup = BuildSetup(required_python_spec("cpython:3.9.7"))
setup.compile()

Invoke an inspection from python code:

from portable_python.inspector import PythonInspector

inspector = PythonInspector("/usr/bin/python3")
print(inspector.represented())
problem = inspector.full_so_report.get_problem(portable=True)
if problem:
    print("oops, it is not portable!: %s" % problem)

From source, contributions welcome!:

git clone https://github.com/codrsquad/portable-python.git
cd portable-python
python3 -mvenv .venv
.venv/bin/pip install -r requirements.txt -r tests/requirements.txt
.venv/bin/pip install -e .
.venv/bin/portable-python --help
.venv/bin/portable-python inspect /usr/bin/python3

tox -e py311
tox -e style

Build folder structure

portable-python uses this file structure (build/ and dist/ folders configurable):

build/
    ppp-marker/3.9.7/                   # Full installation (after build completes)
    components/                         # Builds of statically compiled extension modules are here
    deps/                               # --prefix=.../deps passed to all component ./configure scripts
    sources/
        openssl-1.1.1k.tar.gz           # Downloaded artifacts (downloaded only once)
dist/
    cpython-3.9.7-macos-arm64.tar.gz    # Ready-to-go portable binary tarball

Guiding principles

  • Focuses on just one thing: compile a portable python, and validate that it is indeed portable, produce outcome in (configurable) ./dist/ folder and that’s it

  • No patches: C compilation is done as simply as possible without modifying the upstream source code. Rely solely on the make/configure scripts, typically via stuff like --enable-shared=no

  • Builds are validated, an important part of the effort was to write up code that is able to inspect a python installation and detect whether it is portable or not (and why not if so).

  • Only the last few non-EOL versions of python are supported (no historical stuff)

  • As time goes on, the code of this tool will evolve so that the latest pythons keep building (but won’t worry that older versions still keep building)

For this repo itself:

  • Code is pure python, it is a CLI with one entry-point called portable-python

    • Can be ran in a debugger

    • 100% test coverage, has a --dryrun mode to help with testing / debugging / seeing what would be done quickly

    • No shell scripts (those are hard to maintain/test/debug)

    • Can be pip install-ed and reused

Metadata

Release files for portable-python 2.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for portable-python 2.1.0
File Size Uploaded Provenance Actions
portable_python-2.1.0.tar.gz 91.5 kB With provenance Details for portable_python-2.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for portable-python 2.1.0
File Interpreter ABI Platform Actions
portable_python-2.1.0-py3-none-any.whl Python 3 none any Details for portable_python-2.1.0-py3-none-any.whl

Total release size: 136.7 kB

Release files / portable_python-2.1.0.tar.gz

Download URL portable_python-2.1.0.tar.gz
Size 91.5 kB
Tags Source
SHA-256 checksum
How to use checksums
9f0e57f3bca85dc78bd3c323b8f88c1f7d727ad2a6b77187a68aaf5cb1846550
BLAKE2b-256 checksum
How to use checksums
9c9e21a95e356fffd398fbbd7ca0635ea7d44138cd246b5bb14271c29fea8e15
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

Release files / portable_python-2.1.0-py3-none-any.whl

Download URL portable_python-2.1.0-py3-none-any.whl
Size 45.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ea8b93639832d80e2ba9c9cc739f22f8cf2ecd9592ab008664807215c20c41de
BLAKE2b-256 checksum
How to use checksums
bff649c177b8b981c9ded2ab662b4f07cd33e0997865b6fc0984c8ac2ec0a8fa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

Security for portable-python 2.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for portable_python-2.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

2.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page