Overview of PEX and .pex files
main.pex file, providing a deployment solution similar to virtualenv.repository·main·Indexed 26 days ago
https://github.com/pex-tool/pexA library for generating self-contained, executable Python environments. PEX packages applications and their dependencies into a single .pex file for easy deployment across platforms. It supports specifying requirements via pip or setuptools, defining entry points through scripts or modules, and building for specific target platforms. Advanced features include the `scie` flag for embedding Python interpreters, `bdist_pex` for setuptools integration, and tools for deploying PEX applications in containers using venv.
.pex file, providing a deployment solution similar to virtualenv.PEX files are self-contained, executable Python virtual environments. They are constructed as zip files containing a #!/usr/bin/env python shebang and a special __main__.py file. This structure allows them to be treated as executable Python programs via the Python importer, following the principles outlined in PEP 441.
Key benefits include:
scp to move a single file.You can install the pex tool using pip:
$ pip install pexAlternatively, if you want to build the binary from a git clone using uv to keep your Python environment clean:
$ uv run dev-cmd package
$ cp dist/pex ~/bin$ pip install pexIn restricted network environments, you can redirect where a lazy PEX fetches its Python distribution by using the PEX_BOOTSTRAP_URLS environment variable. This variable should point to a JSON file mapping the expected distribution filename to a custom URL (including file:// paths for local files).
JSON Format:
{
"ptex": {
"<distribution-filename>": "<internal-or-local-URL>"
}
}Workflow to generate a configuration file:
SCIE=inspect <your_pex_scie> | jq '{ptex:.ptex}'.PEX_BOOTSTRAP_URLS=your_config.json ./your_pex.pex, first install it via pip. You can then use pex to bootstrap itself into a standalone executable in a directory like ~/bin. This allows you to use pex in or outside of any virtualenv, provided ~/bin is in your $PATH.By default, PEX commands create ephemeral environments that are garbage collected after execution. To save a standalone executable PEX file to disk, use the -o PATH or --output PATH option.
Example: Packaging Ansible as a standalone executable.
Once saved, the .pex file is an executable environment that can be run directly.
$ pex ansible -c ansible -o ansible.pex
$ ./ansible.pex --helpIf you want to reduce the size of your PEX file and your deployment machines have internet access, use --scie lazy. Instead of embedding the full Python distribution, the PEX will fetch the required distribution from the internet only when needed. If the same Python distribution has been used by another PEX on that machine previously, the fetch is skipped and the local version is used.
pex cowsay -c cowsay --inject-args=-t --scie lazy -o cowsayFor the smallest footprint and lowest latency in containers, use the PEX venv tool.
--include-tools (or --venv).Note: The container must contain the Python interpreter used to build the PEX.
FROM python:3.10-slim as deps
COPY /my-app.pex /
RUN PEX_TOOLS=1 /usr/local/bin/python3.10 /my-app.pex venv --scope=deps --compile /my-app
FROM python:3.10-slim as srcs
COPY /my-app.pex /
RUN PEX_TOOLS=1 /usr/local/bin/python3.10 /my-app.pex venv --scope=srcs --compile /my-app
FROM python:3.10-slim
COPY --from=deps /my-app /my-app
COPY --from=srcs /my-app /my-app
ENTRYPOINT ["/my-app/pex"]You can control the Python interpreter used by the PEX file in two ways:
--python: Sets the default interpreter (e.g., PyPy) in the PEX hashbang.--python-shebang: Specifies an explicit, absolute path for the Python shebang line (useful for non-standard locations or interpreters not on $PATH).Note: The interpreter can also be manipulated at runtime using the PEX_PYTHON environment variable.
PEX provides a bdist_pex command for setuptools to build executables for Python projects following standard naming conventions.
pip-7.2.0.pex). If no console scripts exist, it produces an environment PEX that drops into an interpreter.--bdist-all to build all defined entry_points instead of just the namesake script. This om does not append version numbers or the .pex suffix.--bdist-dir to control where the files are written.By default, a PEX scie executes the configured entry point. However, you can use the --scie-busybox flag to include a specific set of commands (modules, functions, or console scripts) within the scie. This allows the scie to act as a multi-tool container.
To use a command from a BusyBox scie, you can either:
SCIE_BOOT environment variable.If no command is provided, the scie will list available commands and prompt for selection.
To run a WSGI app (like Flask or Django) as a PEX, you must bundle Gunicorn as a dependency and set it as the entry point. Since Gunicorn cannot enter the PEX to find the app, the PEX must invoke Gunicorn and pass the app instance name as a runtime argument.
Build the PEX with Gunicorn and your framework (e.g., Flask):
pex flask gunicorn myapp -c gunicorn -o ~/service.pex
Run the PEX by passing the app instance and optional config:
./service.pex myapp:appinstance -c /path/to/gunicorn_config.py
$ pex flask gunicorn myapp -c gunicorn -o ~/service.pex
$ service.pex myapp:appinstance -c /path/to/gunicorn_config.py