Python PEX Executables — Core Concepts

What PEX is

PEX (Python EXecutable) is a tool that creates self-contained Python environments packaged as single .pex files. These files are executable zip archives that bundle your code and all its dependencies. When run, Python’s built-in zipimport mechanism loads everything directly from the archive.

Unlike PyInstaller, PEX does not embed the Python interpreter. The target machine needs a compatible Python version installed. What PEX eliminates is the dependency installation step — no pip install, no virtualenv, no requirements.txt dance.

How it works

Building a PEX file follows a predictable flow:

  1. Resolve dependencies — PEX reads your requirements and downloads wheels for the target platform.
  2. Pack into a zip — Your code, all dependency wheels, and a bootstrap script are zipped together.
  3. Add a shebang — The file starts with #!/usr/bin/env python3, making it directly executable on Unix systems.
  4. Seal the archive — The result is a single .pex file, typically 5-50 MB depending on your dependencies.
# Basic usage
pex requests flask -e myapp:main -o myapp.pex

# From a requirements file
pex -r requirements.txt -e myapp:main -o myapp.pex

# Run it
./myapp.pex

The -e flag sets the entry point (module:function), and -o names the output file.

Why companies use PEX at scale

PEX became popular at Twitter (where it was created) and spread to companies like Netflix, Dropbox, and Stripe. The reasons are practical:

  • Atomic deployments — copy one file to a server, run it. No partial installs, no broken dependency states.
  • Reproducibility — the same .pex file runs identically everywhere. No “works on my machine” problems.
  • Hermetic builds — dependencies are locked at build time. A .pex file built today will use the exact same library versions months later.
  • Fast rollbacks — keep the previous .pex file around. Rolling back means swapping one file.

PEX vs other packaging tools

FeaturePEXPyInstallerpip + venv
Includes Python interpreterNoYesNo
Single file outputYesYes (onefile mode)No
Cross-platform buildsPlatform-specific wheelsPlatform-specificPlatform-specific
Startup overheadLow (~100ms)Medium (1-10s for onefile)None
Target audienceServer deploymentsDesktop end usersDevelopers

PEX shines in server-side deployments where Python is already installed. PyInstaller is better for distributing to end users who may not have Python.

Platform-specific considerations

PEX files that include compiled extensions (NumPy, pandas, etc.) are tied to the platform they were built for. A .pex built on macOS with ARM wheels will not work on x86 Linux.

To build for a different platform:

# Build for Linux x86_64 from any platform
pex --platform linux_x86_64-cp-3.11-cp311 \
    numpy pandas -e myapp:main -o myapp.pex

For pure-Python projects (no compiled extensions), the same .pex file works everywhere.

Dependency resolution modes

PEX supports two resolver backends:

  • pip (default) — uses pip’s resolver under the hood. Familiar behavior, handles most cases.
  • pex (built-in resolver) — PEX’s own resolver, faster for complex dependency trees and better at handling platform-specific resolution.
# Use the built-in resolver
pex --resolver-version pip-2020-resolver requests -o app.pex

Common misconception

“PEX files are just renamed zip files you could make by hand.”

Not quite. PEX adds a sophisticated bootstrap layer that handles sys.path manipulation, dependency isolation, wheel unpacking for compiled extensions, and interpreter compatibility checks. The zip format is the container, but the runtime bootstrap is what makes it work reliably.

One thing to remember: PEX gives you atomic, reproducible Python deployments in a single file — ideal for server environments where Python exists but dependency management is a headache.

pythonpexpackagingexecutablesdeployment

See Also

  • Python Appimage Distribution An AppImage is like a portable app on a USB stick — download one file, double-click it, and your Python program runs on any Linux computer without installing anything.
  • Python Briefcase Native Apps Imagine a travel agent who repacks your suitcase for each country's customs — Briefcase converts your Python app into proper native packages for every platform.
  • Python Flatpak Packaging Flatpak wraps your Python app in a safe bubble that works on every Linux system — like a snow globe that keeps your program perfect inside.
  • Python Mypyc Compilation Your type hints are not just for documentation — mypyc turns them into speed boosts by compiling typed Python into fast C extensions.
  • Python Nuitka Compilation What if your Python code could run as fast as a race car instead of a bicycle? Nuitka translates Python into C to make that happen.