Python PEX: Создание Исполняемых Python-Приложений с Зависимостями

Python PEX: Создание Исполняемых Python-Приложений с Зависимостями


Python PEX: Создание Исполняемых Python-Приложений с Зависимостями

Полное руководство с примерами и лучшими практиками


Что такое PEX?

PEX (Python Executable) — технология упаковки Python-проектов в единый исполняемый файл (с расширением .pex), содержащий код, зависимости и метаданные. Разработанный Twitter (ныне X) и поддерживаемый сообществом, PEX решает ключевые проблемы:

  • Упрощение деплоя (без pip install).
  • Изоляция зависимостей.
  • Кроссплатформенность (при наличии совместимого Python).

Как это работает?
PEX-файл — это ZIP-архив со структурой:

├── PEX-INFO           # Метаданные (зависимости, точка входа)
├── .bootstrap/        # Скрипты инициализации
├── .deps/             # Установленные пакеты (wheels)
└── your_code.py       # Ваш код

При запуске PEX распаковывает зависимости в изолированное окружение и выполняет код.


Установка PEX

pip install pex

Проверка: pex --versionpex 2.1.143


Создание PEX: Пошаговые Примеры

Пример 1: Простой скрипт с внешней зависимостью

  1. Исходный код (main.py):
import requests
from colorama import Fore, init

init(autoreset=True)

def get_ip():
    response = requests.get("https://httpbin.org/ip")
    return response.json()["origin"]

if __name__ == "__main__":
    ip = get_ip()
    print(Fore.GREEN + f"Ваш IP: {ip}")
  1. Зависимости (requirements.txt):
requests
colorama
  1. Сборка PEX:
pex -r requirements.txt -e main:get_ip -o ip_tool.pex
  • -r requirements.txt: установка зависимостей.
  • -e main:get_ip: точка входа (файл:функция).
  • -o ip_tool.pex: имя выходного файла.

Запуск:

./ip_tool.pex
# Результат: Ваш IP: 192.168.1.1 (в цвете)

Пример 2: Пакет с setup.py
Структура проекта:

myapp/
├── setup.py
└── myapp/
    ├── __init__.py
    └── cli.py
  1. setup.py:
from setuptools import setup, find_packages

setup(
    name="myapp",
    version="0.1",
    packages=find_packages(),
    entry_points={"console_scripts": ["myapp = myapp.cli:main"]},
    install_requires=["click>=8.0", "tabulate"],
)
  1. cli.py:
import click
from tabulate import tabulate

@click.command()
@click.option("--name", prompt="Ваше имя", help="Имя пользователя")
def main(name):
    table = [["Привет,", name], ["PEX", "работает!"]]
    print(tabulate(table, tablefmt="fancy_grid"))
  1. Сборка PEX:
pex . -c myapp -o app.pex  # '.' указывает на текущий каталог с setup.py
  • -c myapp: имя консольного скрипта из entry_points.

Запуск:

./app.pex --name=Анна
# Вывод таблицы с приветствием.

Продвинутые Сценарии

1. Зависимости из разных источников

pex requests "flask>=2.0" git+https://github.com/user/repo.git -o app.pex

2. Multi-платформенная сборка
Укажите платформы явно (требует предварительной компиляции wheels):

pex -r requirements.txt \
    --platform=manylinux2014_x86_64 \
    --platform=macosx_12_0_arm64 \
    -o app.pex

3. Включение ресурсов
Добавьте файлы через --resources:

pex -r requirements.txt -e main:main \
    --resources-dir templates/="templates/*" \
    -o app.pex

4. Переменные окружения

pex --python=python3.11 -o app.pex  # Фиксация версии Python

Лучшие Практики

  1. Минимизация размера:
    Используйте --no-index с локальным кэшем wheels:

    pex -r requirements.txt --no-index --find-links=./wheels_dir -o app.pex
  2. Тестирование PEX:
    Запуск тестов внутри PEX:

    pex -r requirements.txt -p pytest -o test.pex
    ./test.pex tests/
  3. Интерактивный режим:

    ./app.pex -m IPython  # Запуск IPython с зависимостями
  4. Интеграция с Docker:

    FROM python:3.11-slim
    COPY app.pex /app.pex
    ENTRYPOINT ["/app.pex"]

Ограничения PEX

  • Нет статической линковки: Требует установленного Python.
  • Размер файла: Может быть крупным (все зависимости внутри).
  • Системные библиотеки: Не включает низкоуровневые зависимости (например, libssl).

PEX vs. Другие Инструменты

ИнструментПреимуществаНедостатки
PEXЗапуск без установки, изоляция, кроссплатформенностьТребует Python, размер файла
PyInstallerПолностью автономный бинарникСложность сборки под несколько ОС
DockerПолная изоляция, любые зависимостиТребует Docker, тяжёлые образы
zipappВстроен в Python, простойНет управления зависимостями

Отладка PEX

  • Просмотр содержимого:
    unzip -l app.pex
  • Verbose-режим:
    PEX_VERBOSE=5 ./app.pex
  • Путь к кэшу зависимостей:
    export PEX_ROOT=/custom/cache/path

Заключение

PEX — мощный инструмент для:
✅ Быстрого деплоя скриптов и приложений.
✅ Создания переносимых CLI-утилит.
✅ Упрощения CI/CD-пайплайнов.

Пример итогового workflow:

# Сборка
pex -r requirements.txt -e app:main --platform=manylinux2014_x86_64 -o release.pex

# Деплой на сервер
scp release.pex user@server:/app/

# Запуск
ssh user@server "/app/release.pex"

Используйте PEX для проектов, где важна скорость развёртывания и переносимость!


Дополнительные ресурсы:

Статья охватывает ключевые аспекты PEX: от базовых примеров до продвинутых сценариев. Для глубокого изучения рекомендуется экспериментировать с реальными проектами и изучать исходный код PEX на GitHub.