Library / SDK
pex-tool/pex avatar
pex-tool/pex

pex: Python executables, lock files and venvs from one tool

A tool for generating .pex (Python EXecutable) files, lock files and venvs.

4,227 stars322 forksPythonApache-2.0

At a glance

What is it?
pex-tool/pex builds .pex files, executable Python environments you can copy between machines. It suits engineers who ship Python applications as single files and want lock files and virtual environments from the same CLI.
Who is it for?
pex fits teams that deploy Python applications as single files and want the same tool to produce lock files and virtual environments. It is the wrong choice if you want a container image or a system package manager to own the runtime, or if your dependencies need post-install system work that a copied file cannot perform.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 2, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The deployment problem pex was built for

Installing a Python application on another machine usually means recreating an environment: a matching interpreter, a set of dependencies, and the application code. pip and virtualenv handle this on a machine you control. They are less convenient when the target is a build artifact you want to copy, or a machine where you would rather not run a package manager at all.

pex addresses that by producing .pex files. The README describes them as "executable Python environments in the spirit of virtualenvs" and says pex is an expansion on the ideas in PEP 441. The intended workflow is that deploying a Python application becomes as simple as cp. A pex file can also bundle multiple platform-specific Python distributions, which the README says makes a single file portable across Linux and OS X.

The audience is therefore engineers who package Python applications for distribution rather than people managing a single long-lived virtualenv on one host. The README also notes that build systems including Pants, Buck and {py}gradle support building .pex files directly, so teams already using those tools can produce pex artifacts without invoking the CLI by hand.

What a .pex file contains and how the CLI composes it

The pex command resolves requirements, gathers the distributions that satisfy them, and writes them into one executable file. The repository layout mirrors that split: the pex/ package holds the tool and runtime, tests/ and testing/ hold the suites, and package/ holds packaging inputs. The build backend is declared in pyproject.toml, where build-backend is pex_build.setuptools.build and the delegate-build-backend is setuptools.build_meta. That indirection exists so the same source tree can produce metadata for very old and very new Pythons; the comment in pyproject.toml says the setup.cfg metadata is kept because pyproject.toml project support arrived in setuptools 61.0.0, which requires Python 3.7 or newer.

At run time the options compose. The README states that most pex options work together, so a requirement specification, an entry point and an interpreter selection can appear in one command. Interpreter selection is explicit: the -c/--console-script flag builds a standalone executable for a console_scripts entry point, and --python=pypy selects a different interpreter type. Short and long forms are both available, and pex --help lists the full set.

The lock file side of the tool is visible in the build configuration too. pyproject.toml defines a script-locks entry that runs uv export with --format pylock.toml, --frozen and --all-extras to produce a lock. That is the project's own build plumbing rather than a user-facing command, but it shows the lock format the toolchain targets.

Install pex and build your first executable

Installation is a single pip command, which the README gives as pip install pex. After that the pex command is on your PATH.

bash
pip install pex

There is a second route for people who want to keep their environment empty. The README describes building pex in a git clone using uv, which produces a pex binary in dist/pex that you can copy onto your PATH:

bash
uv run dev-cmd package
cp dist/pex ~/bin

The README frames that approach as more in line with what pex does philosophically, since it avoids installing pex's own dependencies into your working environment.

With the tool installed, the fastest way to see it work is an ephemeral environment. This runs webserver.py against an environment containing flask without creating a virtualenv first:

bash
pex flask -- webserver.py

The arguments after the double dash are passed to the script, so the same pattern works for a tool that takes flags. The README gives a Sphinx example that launches the sphinx:main entry point and forwards --help:

bash
pex sphinx -e sphinx:main -- --help

To produce a file you can copy elsewhere, add an output file. This builds a standalone executable for the pex-tools console script found in pex 2.1.35 and newer:

bash
pex "pex>=2.1.35" --console-script pex-tools --output-file pex-tools-executable.pex

The README notes that -c is the short form of --console-script and -o the short form of --output-file, and that the same command can target a different interpreter with --python=pypy. To capture an existing environment instead of naming packages, the README shows freezing a virtualenv through pip:

bash
pex $(pip freeze) -o my_virtualenv.pex

Running ./my_virtualenv.pex afterwards executes that captured set of dependencies.

Where pex stops being the right tool

pex packages Python code and Python distributions. It does not package the operating system libraries your dependencies link against, and the README does not claim otherwise. A dependency that needs a system package, a compiler at install time, or a service running alongside it will not be satisfied by copying a pex file to a bare host.

The interpreter question is the other boundary. The README states that pex files can include multiple platform-specific Python distributions and that a single file can be portable across Linux and OS X. That is a statement about the distributions pex bundles, not a guarantee for every dependency: a wheel with compiled extensions is tied to the platform and Python version it was built for, and a pex file built on one platform will not silently acquire wheels for another. If your dependency set is mostly source distributions, expect the build side to do more work.

The project's own Python support range is wide but not unlimited. pyproject.toml declares requires-python as >=2.7,<3.16 with 3.0 through 3.4 excluded, and the file comments explain that this breadth is deliberate so the tool can run under old interpreters. That is useful if you have legacy hosts, and it is also a sign that the codebase carries compatibility scaffolding you will not need on a modern fleet.

Finally, pex is a packaging tool, not an orchestrator. It gives you a file; it does not schedule it, restart it, or roll it back. The README does not document rollback, health checks or process supervision, so those remain yours to design.

pex compared with a container image

The closest alternative for many teams is a container image. A Dockerfile pins a base image, installs dependencies into that image's filesystem, and ships the whole thing. The difference in approach is what gets frozen: a container freezes the operating system layer along with your application, while a pex file freezes the Python environment and expects the host to supply the rest.

That makes containers the better answer when your application depends on system packages, when you want the runtime and the app versioned together, or when your deployment target is already a container platform. pex is the better answer when the target is a host you do not fully control, when you want an artifact measured in megabytes that starts without a container runtime, or when you want the same dependency resolution to feed both a lock file and an executable.

The trade-off is not free in either direction. A pex file assumes a compatible interpreter exists on the target, or that you bundled one. A container assumes a container runtime exists on the target. The README's claim that deployment becomes as simple as cp is accurate only within the first assumption. Teams that already build images and are happy with them will find little reason to add pex; teams that ship Python tools to heterogeneous hosts, CI runners or user machines will find the single-file model removes a layer.

Maintenance, releases and licence

The repository is not archived, and the last push was on 2026-09-18. Releases are frequent: v2.103.0, v2.103.1 and v2.103.2 all landed between 2026-09-16 and 2026-09-18. That cadence means version pinning matters more than usual. If you script pex in CI, pin the version you install rather than tracking the latest, because the CLI surface can move between minor releases and the README's option list is a snapshot.

Development is driven through uv and dev-cmd. The README says to install uv and then run the test suite with uv run dev-cmd, and that dev-cmd --list shows the available commands. It recommends a shell alias, conventionally uvrc, for the repeated uv run dev-cmd prefix. Individual tests accept passthrough arguments to pytest, for example uvrc test-py37-integration -- -k test_reproducible_build, which the README gives as a way to run a specific test. Pex can also be run from a source checkout with python -m pex.

On licensing, pex is Apache-2.0. The pyproject.toml build configuration sets license = "Apache-2.0" with license-files = ["LICENSE"], and the README states the same. Apache-2.0 is permissive and includes a patent grant, but you should read the LICENSE file in the repository for the terms that apply to you rather than treating this summary as legal advice. If you redistribute a pex file that bundles third-party distributions, those distributions carry their own licences, and pex does not consolidate them for you.

Editorial conclusion

pex fits teams that deploy Python applications as single files and want the same tool to produce lock files and virtual environments. It is the wrong choice if you want a container image or a system package manager to own the runtime, or if your dependencies need post-install system work that a copied file cannot perform. Before adopting it, check the interpreter range in pyproject.toml (>=2.7,<3.16, excluding 3.0 through 3.4) against your fleet, and run pex --help to confirm the options you plan to script exist in the version you install.

Frequently asked questions

What is pex-tool/pex used for?

It generates .pex files, which the README describes as executable Python environments in the spirit of virtualenvs, and it also produces lock files and venvs. The intended result is that deploying a Python application becomes as simple as copying one file.

How do I install pex?

The README gives pip install pex as the installation command. It also documents building a pex binary in a git clone with uv run dev-cmd package and copying dist/pex onto your PATH.

Can I build a standalone executable for a console script with pex?

Yes. The README shows pex "pex>=2.1.35" --console-script pex-tools --output-file pex-tools-executable.pex, which builds a standalone executable for the pex-tools console script found in pex 2.1.35 and newer. The short forms -c and -o are also documented.

Which Python versions can pex run under?

pyproject.toml declares requires-python as >=2.7,<3.16 with 3.0 through 3.4 excluded. The file comments say this wide range is deliberate so the tool also supports very old interpreters.

Official sources

  1. License: Apache-2.0
  2. pex-tool/pex on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pex-tool-pex.svg)](https://hysenlabs.com/projects/pex-tool-pex)