Suppose you have a package that imports a lot of weird modules and you’d like to share this package without forcing end users to install a bunch of stuff. You can bundle this into a PEX file and everyone will live happily ever after.
PEX Files
Well, it’s a carefully crafted zip file of egg files with a hashbang prepended onto it. I first learned about them in this YouTube video. Here is the documentation. If you open a PEX file without any arguments, it will open a Python interpreter with whatever modules it was bundled with. If you give it a Python script it will run that script with whatever modules it was bundled with.
Installation
I had to install wheels
before I could install PEX.
pip install wheel pip install pex
Example
Suppose you have your own package with the following structure:
myStuff/ |--myStuff/ | |--__init__.py | `--myStuff.py `--setup.py
We’ll assume that your setup.py
script looks like this,
#!/usr/bin/env python from setuptools import setup, find_packages setup( name="myStuff", version="1.1", author="Mr. Coffee", description="A simple PEX example", install_requires=['weirdStuff'], packages=find_packages() )
We’ll assume further that you’ve organized myStuff.py
as a bunch of functions, a main()
function and an if __name__=="__main__":
statement, like this,
#!/usr/bin/env python import weirdStuff def fct_1(): pass def fct_2(): pass def main(): fct_1() fct_2() if __name__ == "__main__": main()
Then we can build a PEX file by requiring weirdStuff
, sourcing the myStuff
package, and executing the myStuff.main()
by specifying that endpoint,
pex -r weirdStuff -s myStuff -e myStuff.myStuff:main -o out.pex
So, the -r
flag requires weirdStuff
, the -s
flag sources your package, and the -e
flag specifies the endpoint–that means that after weirdStuff
and myStuff
is imported, myStuff.myStuff.main()
is called. Now you can shoot this guy to a colleague and they can execute it by calling ./out.pex
at the command line, assuming that they have Python installed.