Skip to content

Instantly share code, notes, and snippets.

@simeonf
Last active January 9, 2024 05:11
Show Gist options
  • Save simeonf/062af826e79259bc7686 to your computer and use it in GitHub Desktop.
Save simeonf/062af826e79259bc7686 to your computer and use it in GitHub Desktop.
Creating a PEX from a python script

So you want to create a pex that packages your script and its dependencies?

Ok - first to make our script! Call it foo.py:

import requests

if __name__ == '__main__':
  req = requests.get("https://raw.githubusercontent.com/pantsbuild/pex/master/README.rst")
  print req.text.split("\n")[0]

It's a requests hello world program. To package it we need a minimal setup.py for distributing a script. Put it in the same directory:

from distutils.core import setup
setup(name='foo',
    version='1.0',
    scripts=['foo.py'],
    )

Now that our script is packageable we can use pex to build an executable out of it:

$ pex . requests -c foo.py -o foo.pex -f dist

Briefly - requests and . are our dependencies. -c foo.py tells pex what to run. And -o foo.pex creates the output file.

You should get a foo.pex file in the same directory. Run it to see the script execute:

$ ./foo.pex
PEX

And you can unzip the pex to see the contents including the packaged dependencies:

$ unzip -t foo.pex
... much output not shown...
@eddiewebb
Copy link

eddiewebb commented Apr 12, 2018

Thank you! this is super helpful. My main script works, but complains it can't find other local files.

queueBuildUntilFrontOfLine.py

#!/usr/bin/env python
import sys
import time
import circleci #local file
import environment #local file

do stuff...

layout

 ls -l src/*.py
-rwxr-xr-x  1 n0158588  staff  1419 Apr 12 12:50 src/queueBuildUntilFrontOfLine.py
-rw-r--r--  1 n0158588  staff  1131 Apr 12 12:50 src/circleci.py
-rw-r--r--  1 n0158588  staff   209 Apr 12 08:47 src/environment.py
-rw-r--r--  1 n0158588  staff   161 Apr 12 15:07 src/setup.py

python foo.py works fine, but the packaged pex fails.

pex src requests -c queueBuildUntilFrontOfLine.py -o queueBuildUntilFrontOfLine.pex -f src
./queueBuildUntilFrontOfLine.pex

ImportError: No module named circleci

Do you have any advice? I'm struglging to make sense of https://pex.readthedocs.io/en/stable/buildingpex.html#specifying-requirements

@kneufeld
Copy link

If you find the answer please post it here. I find the docs for pants and pex to be terrible. There is no single complete example and all the descriptions are overly technical and examples too simple.

@wangshan
Copy link

try to make circleci.py a module, ie, put it in a directory like this:

circleci
  |__ circleci/circleci.py
  |__ circleci/__init__.py
  |__ setup.py

in setup.py write this:

from distutils.core import setup
setup(name='circleci',
    version='1.0',
    packages=['circleci'],
    )

@archenroot
Copy link

By following the original content I get:
Unable to parse /home/zangetsu/.pex/install/foo-1.0-py3-none-any.whl.ee5c21cd6d1cd79925b2f4a751c96970ec7248cf/foo-1.0-py3-none-any.whl/bin/foo.py. PEX script support only supports Python scripts.

@archenroot
Copy link

Ok, issue with Python 3.6 and print function change....

@shearn89
Copy link

shearn89 commented Apr 15, 2021

Shameless self-promotion, but I've just put together a simple demo repo for packaging python scripts as PEX files, because the documentation was rubbish. https://www.shearn89.com/2021/04/15/pex-file-creation with source code here: https://github.com/shearn89/pex-demo

@Caleb9
Copy link

Caleb9 commented Jan 16, 2022

Thanks so much for the article, I got it working finally :). One extra thing I needed to do to make this work was to add a python shebang #!/usr/bin/env python3 on top of main.py file. Supposedly there's been a change in pex 2.1.46 making this necessary. Note that this particular shebang works on Debian and its derivatives, but might be different for other distros (not sure though).

@shearn89
Copy link

@Caleb9 ah cool, glad it helped! I'll update the article with a link to that post, cheers for the heads up!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment