Skip to main content

Portable python binaries

Project description

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

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

setup = BuildSetup("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

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

portable_python-1.9.5.tar.gz (46.6 kB view details)

Uploaded Source

Built Distribution

portable_python-1.9.5-py3-none-any.whl (40.7 kB view details)

Uploaded Python 3

File details

Details for the file portable_python-1.9.5.tar.gz.

File metadata

  • Download URL: portable_python-1.9.5.tar.gz
  • Upload date:
  • Size: 46.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.7

File hashes

Hashes for portable_python-1.9.5.tar.gz
Algorithm Hash digest
SHA256 e0f277fec3c585134d5d2a834f03745732527d9be020fd906bcbf3928e26980f
MD5 bce2c59fa62e00c371ca2491bbc359b9
BLAKE2b-256 9e3a16a0749e7c06bab912860000de42fb3217208a3d0a3574876860e697a8c7

See more details on using hashes here.

Provenance

The following attestation bundles were made for portable_python-1.9.5.tar.gz:

Publisher: release.yml on codrsquad/portable-python

Attestations:

File details

Details for the file portable_python-1.9.5-py3-none-any.whl.

File metadata

File hashes

Hashes for portable_python-1.9.5-py3-none-any.whl
Algorithm Hash digest
SHA256 5ecf4bac9aa6886705308b29c26b069431f98965bfd2c8df6a02d67253b67247
MD5 ebfdb51c3a5a10e98b62c7cba65c0a2f
BLAKE2b-256 d80edaad18b4f367e561d30a5ebe408808000368cbcff49b1d29b408400cb980

See more details on using hashes here.

Provenance

The following attestation bundles were made for portable_python-1.9.5-py3-none-any.whl:

Publisher: release.yml on codrsquad/portable-python

Attestations:

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page