pex

Introduction

In a couple of words: pex helps create self-contained executable Python virtual environments.

https://pex.readthedocs.io/

https://www.youtube.com/watch?v=NmpnGhRwsu0

Bootstrap

Bootstrap pex with these steps:

  • create a short lived Python virtual environment;

  • install pex in this environment;

  • use the newly installed pex to create a pex file:

    • containing the pex project as well as the dependencies; and

    • having the pex console script as its entry point.

With Python 3 and the ~/bin directory on the PATH this could look like this:

shell console
$ python3 -m venv pexenv
$ . pexenv/bin/activate
(pexenv) $ pip install pex
(pexenv) $ pex \
> 'pex[requests,cachecontrol]' \
> --console-script=pex \
> --output-file=~/bin/pex
(pexenv) $ deactivate
$ rm --force --recursive pexenv
$ which pex
$ pex --version

The pexenv Python virtual environment can be deleted immediately afterwards. pex can be used directly since it is self contained in its own Python virtual environment within the ~/bin/pex file.

Overview

Per default pex starts the Python interpreter in a dynamically created empty virtual environment.

shell console
$ pex
Python 2.7.12 (default, Nov 19 2016, 06:48:10)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> exit()

It is possible to select which Python interpreter should be used.

shell console
$ pex --python=python3
Python 3.5.2 (default, Nov 17 2016, 17:05:23)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> exit()

pex allows to specify which Python projects should be installed in the virtual environment.

shell console
$ pex 'requests<2.0.0' 'setuptools==30'
Python 3.5.2 (default, Nov 17 2016, 17:05:23)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> import requests
>>> requests.__version__
'1.2.3'
>>> import setuptools
>>> setuptools.__version__
'30.0.0'
>>> exit()

The dependencies can be specified via a pip requirements.txt file.

shell console
$ pex --requirement=requirements.txt

pex also allows to specify an entry point that should be executed from within the virtual environment.

shell console
$ pex 'httpie==0.9.6' --console-script=http -- --version
0.9.6
$ pex --python=python3 --entry-point=http.server
Serving HTTP on 0.0.0.0 port 8000 ...

Finally pex allows to write this self-contained executable virtual environment into a single file.

shell console
$ pex --python=python3 --entry-point=http.server --output-file=server.pex
$ ./server.pex
Serving HTTP on 0.0.0.0 port 8000 ...

Inspect

Since pex files are ZIP archives, inspecting their content is very straighforward.

shell console
$ python -m zipfile -l example.pex
$ unzip -l example.pex

It is a good idea to check that only the required and necessary dependencies are included. Nothing more and nothing less should be found in the .deps directory.

setuptools

To easily build a pex executable with setuptools use the bdist_pex command. bdist_pex will use the console_scripts entry point bearing the exact name of the Python project itself.

setup.py
import setuptools

NAME = 'Example'

setuptools.setup(
    name=NAME,
    entry_points={
        'console_scripts': [
            '{}=example.app:run'.format(NAME),
        ],
    },
    # ...
)

Requirements

For a stricter control over the dependencies added to the pex file, a requirements.txt file can be specified via the --pex-args option.

shell console
$ python setup.py bdist_pex --pex-args='--requirement=requirements.txt'