TLDR: Pants fetches OS X specific wheels bc I'm developing on Mac. How can I avoid this, or specify that I will deploy to Ubuntu?
Full story:
Trying to package a Python application with Pants. Going great so far, but ran into a problem which I've been stuck at for a while. I'm developing on a macbook but deploying to EC2 Ubuntu.
Here's what I've done so far:
- Created virtualenv.
- Added BUILD files to applications, with the suggested 3rd party pattern for third party packages.
- Ran
./pants run.py backend:admin_server
which runs fine and generateddist/admin_server.pex
- Scp that .pex onto a fresh EC2 Ubuntu box.
However when I run the application there, I get:
Failed to execute PEX file, missing compatible dependencies for:
mysql-python
pycrypto
The problem seems to be that Pants takes OS X specific wheels for these 2:
pex: - MySQL_python-1.2.5-cp27-none-macosx_10_11_intel.whl pex: - pycrypto-2.6.1-cp27-none-macosx_10_11_intel.whl
How can I avoid that, or specify which OS they should run on?
Here's the full output:
ubuntu@ip-***:~$ export PEX_VERBOSE=1
ubuntu@ip-***:~$ python admin_server.pex
pex: Found site-library: /usr/local/lib/python2.7/dist-packages
pex: Found site-library: /usr/lib/python2.7/dist-packages
pex: Tainted path element: /usr/local/lib/python2.7/dist-packages
pex: Tainted path element: /usr/lib/python2.7/dist-packages
pex: Scrubbing from site-packages: /usr/local/lib/python2.7/dist-packages
pex: Scrubbing from site-packages: /usr/lib/python2.7/dist-packages
pex: Scrubbing from user site: /home/ubuntu/.local/lib/python2.7/site-packages
pex: Failed to resolve a requirement: MySQL-python==1.2.5
pex: Failed to resolve a requirement: pycrypto==2.6.1
pex: Unresolved requirements:
pex: - mysql-python
pex: - pycrypto
pex: Distributions contained within this pex:
pex: - six-1.10.0-py2.py3-none-any.whl
pex: - protobuf-2.6.1-py2.7.egg
pex: - setuptools-19.5-py2.py3-none-any.whl
pex: - MySQL_python-1.2.5-cp27-none-macosx_10_11_intel.whl
pex: - pycrypto-2.6.1-cp27-none-macosx_10_11_intel.whl
pex: - futures-3.0.4-py2-none-any.whl
pex: - webapp2-2.5.2-py2-none-any.whl
pex: - requests-2.9.0-py2.py3-none-any.whl
pex: - jmespath-0.9.0-py2.py3-none-any.whl
pex: - beautifulsoup4-4.4.1-py2-none-any.whl
pex: - python_dateutil-2.4.2-py2.py3-none-any.whl
pex: - boto3-1.2.3-py2.py3-none-any.whl
pex: - WebOb-1.5.1-py2.py3-none-any.whl
pex: - cssutils-1.0.1-py2-none-any.whl
pex: - webapp2_static-0.1-py2-none-any.whl
pex: - Paste-2.0.2-py2-none-any.whl
pex: - docutils-0.12-py2-none-any.whl
pex: - botocore-1.3.22-py2.py3-none-any.whl
pex: - protobuf_to_dict-0.1.0-py2-none-any.whl
Failed to execute PEX file, missing compatible dependencies for:
mysql-python
pycrypto
PS: to make sure I didn't include my versions of the python libraries, I pip uninstalled both PyCrypto and MySQL-Python.
One of the nice things about distributing your project as a PEX file is that you can prepare it to run on multiple platforms. For example, one PEX can run on both Linux and Mac platforms. For many projects, there is nothing special to do other than build a PEX. But when your project has dependencies on platform specific binary code, you will need to perform some extra steps.
One example of a library that contains platform specific code is the
psutil
library. It contains C code that it compiled into a shared library when the module is installed. To create a PEX file that contains such dependencies, you must first provide a pre-built version of that library for all platforms other than the one where you are running pants.The easiest way to pre-build libraries is to use the pip tool to build wheels.
This recipe assumes the following:
Let’s take a simple program that references a library and create a pex from it.
With Pants, you can define an executable by defining a python_binary target in a BUILD file:
In the same directory, list the python libraries in a requirements.txt file:
Now, to to make the multi-platform pex, you'll need access to a Linux box to create the linux version of psutil wheel. Copy the requirements.txt file to the linux machine, then, execute the pip tool:
This will create a platform specific wheel file.
Now, you will need to copy the platform specific wheel over to the machine where you want to build your multi-platform pex (in this case, your mac laptop). If you use this recipe on a regular basis, you will probably want to configure a Python Respository to store your pre-built libraries.
We’ll use the same BUILD file setup as in above, but modify python_binary to specify the
platforms=
parameter.You will also need to tell pants where to find the pre-built python packages. Edit
pants.ini
and add:Now, copy the file
psutil-3.1.1-cp27-none-linux_x86_64.whl
over to the mac workstation and place it in a directory namedwheelhouse/
under the root of your repo.Once this is done you can now build the multi-platform pex with
You can verify that libraries for both mac and Linux are included in the pex by unzipping it: