Making PEX files (Python EXecutable)

I was in a situation where I needed to run some python on a machine which didn’t have pip installed and I needed some packages from pip for my script. Therefore I was in a situation where I had to work out how to use the pex tool and “documented” it in this repository. Most of it was based off of this tutorial, which is a really good starting point and describes what each of the pex options means.

What is PEX?

This video sums it up pretty well. The best way I can describe it, is that it’s a tool to create something like JAR files for Python.

Why shave this Yak?

My particular use case was that I had to figure out a way to copy files using the pywinrm library to a Windows host and execute a PowerShell script. My initial attempt was to try to run pex on my Macbook to generate the file, however as the PyWinRM library requires the “cryptography” package, it all went a bit south with Python trying to compile C extensions and failing due to old version of OpenSSL on my Mac.

The “fix” was to build (compile?) it in an Ubuntu container, but this presented it’s own problems in how to actually get the binary out.

How to actually do this?

  • Install pex with “pip install pex”
  • Make a directory for your script
  • In the directory make sure you have an “__init__.py”, “setup.py” and your script in the directory (e.g. wingetmem.py)
  • Ensure that the setup file has the correct contents:
from distutils.core import setup
setup(name='wingetmem',
    version='1.0',
    scripts=['wingetmem.py'],
    py_modules=['wingetmem']
)
  •  Run pex to make the binary, making sure that the script name and function name match what’s in your file:
pex wingetmem pywinrm -e wingetmem:wingetmem -o wingetmem.pex
  • Now, if you’re in the same boat as me and need to extract this out of a Docker image, you’ll need to use the “docker save” command and then untar the resulting file:
docker save --output="ubuntu.tar" 0004626ad875
tar xvf ubuntu.tar
[change into each layer and untar the "layer.tar" file]
[check whether the file is in there]
I’m really not happy about that last step, because it’s a pretty bad kludge. Ideally, we’d push the binary to something like Artifactory or Nexus (artifact repositories) rather than just leaving them on “disk” but to be honest, by the time I got this working I had had enough.
The resulting “.pex” file runs fine in a Linux environment without pip, which is what we were after.

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.