Packaging a Simple Python Script with PEX
Project Page: github/simple-pex
Recently I needed to create a package for a simple Python CLI tool which includes all dependencies. It turns out that there is a great tool PEX which can build an executable zip Python package.
That’s exactly what I needed, but unfortunately the documentation for my simple use case was sorely lacking. Described here is how to get PEX working to package a simple CLI tool.
Requirements
Using Python3 and PEX as installed by pip
Structure
Key factors
- setup.py is required to allow building a wheel for the CLI tool
- source must be in a package directory (even if it’s only one file)
/setup.py /samplepkg/ /samplepkg/__init__.py /samplepkg/main.py
setup.py
The setup.py
contains a package description. More details can be found here.
init.py
Empty file to mark samplepkg
as a package directory
main.py
The actual CLI code entry point
Build
PEX requires first that we build a wheel from the sources, then include that wheel in the PEX build
Wheel Build
In the directory containing setup.py run
pip3 wheel -w . .
This will create a wheel in the current directory based on the name
set in setup.py
.
In this example the file generated is
myexample-0.0.0-py3-none-any.whl
PEX Build
Now we build the PEX package.
pex --python=python3 -f $PWD requests myexample -e samplepkg.main -o samplepkg.pex
Breakdown:
-f $PWD
- Causes the current directory to be included in the search path, which allows themyexample-*.whl
to be loadedrequests
- Added dependency on therequests
package. Any other dependencies can be added as extra arguments heremyexample
- Loads the wheel that we just built-e samplepkg.main
- The execution command to run, in this case load ourmain.py
which starts the CLI-o samplepkg.pex
- Write the whole shindig to the shippable filesamplepkg.pex
And try running the generated package
$ ./samplepkg.pex
HELLO WORLD!!
Notes
Python Version
Both pex
and pip wheel
must use the same version of Python. Without being explicit about version it’s possible for the two to get crossed. If this happens you will get an error running pex
: “Could not satisfy all requirements” which means that the wheel file couldn’t be found for the current Python version. You can tell what version was used for pip wheel
by the -pyX-
portion of the wheel file name.
In the code above I explicitly selected Python 3 to be used.
To use Python 2 instead, edit the commands above to replace pip3
with pip2
and pex --python=python3
with pex --python-python2