Книга: Автостопом по Python
Назад: 5. Читаем отличный код
Дальше: Часть III. Руководство по сценариям

6. Отправляем отличный код

В этой главе описываются правила хорошего тона, применяемые при упаковке и отправке кода Python. Вы в основном создаете либо библиотеку Python, которую будут импортировать и использовать другие разработчики, либо отдельное приложение, которое станут применять другие люди, вроде pytest (/).

Система инструментов, связанная с упаковкой кода Python, стала гораздо более удобной в последние несколько лет благодаря усилиям Python Packaging Authority (PyPA) (/) — это сообщество, которое поддерживает pip, Python Package Index (PyPI), а также большую часть инфраструктуры, связанной с упаковкой в Python. Их документация, касающаяся упаковки (/), отлично составлена, поэтому мы кратко рассмотрим два способа размещения пакетов на частном сайте, а также поговорим о том, как загружать код на Anaconda.org — коммерческий аналог PyPI, запущенный Continuum Analytics.

Недостаток распространения кода с помощью PyPI или другого репозитория пакетов заключается в том, что получатель должен понимать, как инсталлировать требуемую версию Python, и иметь возможность использовать инструменты вроде pip для установки других зависимостей для вашего кода.

Это приемлемо при распространении кода для других разработчиков, но не подходит для распространения приложения пользователям, не являющимся программистами. Для этого вам нужно использовать один из инструментов, показанных в разделе «Замораживаем ваш код».

Тем, кто создает пакеты Python для Linux, нелишне обратить внимание на пакет distro (например, файл с расширением .deb на Debian/Ubuntu; он называется дистрибутивом в документации Python). Это потребует выполнения большого объема работы, но мы предложим парочку вариантов в разделе «Упаковка для дистрибутивов, встроенных в Linux». Это похоже на заморозку, но в пакет не входит интерпретатор Python.

Наконец, мы дадим вам отличный совет в разделе «Исполняемые ZIP-файлы»: если ваш код находится в ZIP-архиве (файле с расширением .zip) и имеет определенный заголовок, вы можете просто выполнить ZIP-файл. Когда вы знаете, что у вашей целевой аудитории уже установлен Python и ваш проект состоит только из кода Python, этот вариант приемлем.

Использование словаря и Concepts

До появления PyPA не существовало единого и очевидного способа упаковки (вы можете убедиться в этом в исторической дискуссии на Stack Overflow ( 44076)). В этой главе рассмотрим наиболее важные термины (в глоссарии PyPA (/) вы можете найти и другие определения).

Зависимости. Пакеты Python перечисляют библиотеки, от которых они зависят, в файле requirements.txt (для тестирования или развертывания приложения) или в аргументе install_requires метода setuptools.setup(), когда он вызывается в файле setup.py.

В некоторых проектах могут присутствовать и другие зависимости вроде базы данных Postgres, компилятора C или разделяемого объекта библиотеки C. Они могут быть не указаны явно, но при их отсутствии сборка прервется. Если вы строите библиотеки подобным образом, вам может помочь семинар Пола Керера (Paul Kehrer), посвященный распространению скомпилированных модулей ().

• Дистрибутив. Формат распространения пакета Python (и опционально других ресурсов и метаданных), имеющий форму, которая может быть установлена и затем запущена без дальнейшей компиляции (/).

• Egg. Egg (это формат дистрибутива) представляют собой ZIP-файлы с особой структурой, содержащие метаданные для установки. Формат был введен благодаря библиотеке Setuptools и де-факто являлся стандартом многие годы, но никогда не был официальным форматом упаковки в Python. Был заменен на wheels на момент выхода PEP 427. Вы можете прочесть все о различиях между форматами в разделе Wheel vs Egg руководства по упаковке Python.

Wheel. Это формат дистрибутива, который является стандартом для распространения библиотек Python. Они упаковываются как ZIP-файлы с метаданными, которые pip будет использовать для установки и удаления пакета. Файл имеет расширение .whl и следует соглашению по именованию (указываются платформа, сборка и использованный интерпретатор).

Помимо установленного Python, для запуска обычных пакетов, содержащих лишь код, написанный на Python, не нужно ничего, кроме других библиотек, написанных исключительно на Python, — их можно загрузить с PyPI () (или Warehouse (/) — грядущего нового местоположения для PyPI). Сложности (которые мы попытались обойти, добавив дополнительные шаги по установке в главе 2) возникают, когда библиотека Python имеет зависимости за пределами Python, например в библиотеках C или системных исполняемых файлах. Инструменты вроде Buildout и Conda придут на помощь, когда дистрибутив становится сложным даже для формата are Wheel.

Упаковываем код

Упаковка кода дистрибутива означает создание необходимой структуры файла, добавление требуемых файлов и определение подходящих переменных для comform, релевантных PEP, и текущих правил хорошего тона, описанных в разделе Packaging and Distributing Projects («Упаковка и распространение проектов») в Python Packaging Guide, или требования к упаковке для других репозиториев вроде /.

«Пакет» против «пакета дистрибутива» и против «пакета установки»

Может быть не очень понятно, почему слово «пакет» имеет так много значений. В данный момент мы говорим о пакетах дистрибутива, которые включают (обычные для Python) пакеты, модули и дополнительные файлы, необходимые для определения релиза. Мы также иногда называем библиотеки пакетами установки; они являются высокоуровневыми каталогами пакетов, которые содержат целую библиотеку. Наконец, простой пакет — это любой каталог, содержащий файл __init__.py и другие модули (файлы с расширением *.py). PyPA поддерживает глоссарий терминов, относящихся к упаковке ().

Conda

Если у вас установлен дистрибутив Python от Anaconda, вы все еще можете использовать pip и PyPI, но вашим менеджером пакетов по умолчанию будет conda, а репозиторием пакетов — /. При сборке пакетов мы рекомендуем следовать руководству, расположенному по адресу . Оно заканчивается инструкциями, как загружать пакеты на Anaconda.org.

Если вы создаете библиотеку для научных или статистических приложений — даже если сами не используете Anaconda, — вам понадобится установить дистрибутив для Anaconda, чтобы получить доступ к широкой аудитории научных работников, предпринимателей и пользователей Windows, которые пользуются Anaconda для получения бинарных файлов без лишних забот.

PyPI

Надежная взаимосвязанная система инструментов вроде PyPI и pip позволяет разработчикам максимально легко загружать и устанавливать пакеты как для экспериментов, так и для создания крупных профессиональных систем.

Если вы пишете модуль Python с открытым исходным кодом, PyPI (/), более известный как The Cheeseshop, — походящее место для того, чтобы его разместить. Если для упаковки кода вы выбрали не PyPI, другим разработчикам будет сложнее его найти и использовать как часть их существующих процессов. Они будут относиться к таким проектам с подозрением, поскольку посчитают, что либо проектом плохо управляют и он не готов к релизу, либо проект заброшен.

Правильную и актуальную информацию об упаковке Python вы можете получить из руководства Python Packaging Guide, поддерживаемого PyPA (/).

12995.png

Используйте testPyPI для тестирования и PyPI для реальной разработки

Если вы тестируете настройки упаковки или учите кого-то пользоваться PyPI, можете использовать testPyPI (/) и запускать свои юнит-тесты до отправки реальной версии в PyPI. Как и в случае PyPI, вы должны изменять номер версии при каждой отправке нового файла.

Пример проекта

Пример проекта PyPA по адресу демонстрирует современные правила хорошего тона, касающиеся упаковки проекта Python. В комментариях к модулю setup.py () вы найдете полезные советы и описание важных способов управления для PEP. Общая структура файлов организована согласно требованиям, для каждого файла имеются полезные комментарии, повествующие об их предназначении и о том, что должно в них содержаться.

Файл README отсылает нас к руководству по упаковке (/) и к руководству по упаковке и распространению ().

Используйте pip, но не easy_install

С 2011 года PyPA хорошо поработало для того, чтобы избавиться от заметной путаницы ( 44076) и прекратить дискуссию ( 20404) о том, какой именно способ распространения, упаковки и установки библиотек Python можно назвать стандартным. pip был выбран в качестве установщика пакетов по умолчанию в PEP 453 (/), он устанавливается вместе с Python 3.4 (выпущен в 2014 году) и более поздними версиями.

Каждый из этих инструментов может выполнять задачи, которые другим не под силу, а для более старых систем все еще может понадобиться инструмент easy_install. В таблице от PyPA, расположенной по адресу /, сравниваются pip и easy_install и описываются возможности каждого инструмента.

При разработке собственного кода для установки вам понадобится использовать команду pip install --editable, что позволит редактировать код без переустановки.

Личный PyPI

Если вы хотите устанавливать пакеты не только из PyPI (например, из внутреннего рабочего сервера, на котором хранятся проприетарные пакеты компании или пакеты, проверенные и благословленные вашими командами, отвечающими за безопасность и юридические аспекты), можете сделать это, разместив простой сервер HTTP, который работает из каталога, содержащего пакеты, предназначенные для установки.

Предположим, что вы хотите установить пакет, который называется MyPacka­ge.tar.gz. Имеется следующая иерархия каталогов:

.

|--- archive/

     |--- MyPackage/

          |--- MyPackage.tar.gz

Вы можете запустить сервер HTTP из каталога archive, введя следующую команду в оболочке:

$ cd archive

$ python3 -m SimpleHTTPServer 9000

Это запустит простой сервер HTTP на порту 9000 и перечислит все пакеты (в нашем случае MyPackage). Теперь вы можете установить MyPackage с помощью любого установщика пакетов для Python. Используйте pip в командной строке:

$ pip install --extra-index-url=/ MyPackage

13008.png

Очень важно иметь каталог с таким же именем, что и у пакета. Но, если вы чувствуете, что структура MyPackage/MyPackage.tar.gz избыточна, вы всегда можете изъять пакет из каталога и установить его, указав прямой путь:

$ pip install

Pypiserver

Pypiserver () — это минимальный сервер, совместимый с PyPI. Он может использоваться при обслуживании набора пакетов для easy_install или pip. Содержит полезную функциональность вроде административной команды (-U), которая обновит все пакеты до самых последних версий, имеющихся в PyPI.

PyPI, размещенный на S3

Помимо вышеперечисленных вариантов, вы можете разместить личный сервер PyPI на Simple Storage Service от Amazon, Amazon S3 (/). Для этого вам понадобятся учетная запись для Amazon Web Service (AWS) и сегмент S3. Убедитесь, что вы следуете правилам именования сегмента () (вы, конечно, сможете создать сегмент, который нарушает правила именования, но не получите к нему доступ). Для того чтобы использовать ваш сегмент, сначала создайте виртуальную среду на собственной машине и установите требуемые сторонние библиотеки с помощью PyPI или другого источника. Затем установите pip2pi:

$ pip install git+

Далее следуйте указаниям файла README для pip2pi, где вы сможете прочесть о командах pip2tgz и dir2pi. Вам нужно запустить либо эту команду:

$ pip2tgz packages/ YourPackage+

либо эти две:

$ pip2tgz packages/ -r requirements.txt

$ dir2pi packages/

Теперь загружайте свои файлы. Используйте клиент вроде Cyberduck (/), чтобы каталог с пакетами синхронизировать с вашим сегментом S3. Убедитесь, что вместе с новыми файлами и папками вы загружаете файл packages/simple/index.html.

По умолчанию при загрузке новых файлов в сегмент S3 им присваивается уровень доступа «только для пользователей». Если при попытке установить пакет вы получите код HTTP 403, удостоверьтесь, что правильно настроили уровень доступа: используйте веб-консоль от Amazon, чтобы установить уровень EVERYONE (разрешает чтение всех файлов). Установите ваш пакет с помощью следующей команды:

$ pip install \

  --index-url=/ \

  YourPackage+

Поддержка VCS для pip

Существует возможность получать код непосредственно из системы контроля версий с помощью инструмента pip (для этого следуйте инструкциям по адресу ). Этот способ — альтернатива размещению личного PyPI. Рассмотрим пример команды, использующей pip для получения проекта с GitHub:

$ pip install git+git://git.myproject.org/MyProject#egg=MyProject

В этой команде egg нужно заменить — он носит имя каталога вашего проекта, который вы хотите установить.

Замораживаем код

Фраза «заморозить код» означает «создать отдельный исполняемый пакет, который можно распространять конечным пользователям, на чьих компьютерах не установлен Python». Распространяемый файл или пакет содержит как код приложения, так и интерпретатор Python.

Приложения вроде Dropbox (), Eve Online (/), Civilization IV (/) и клиента BitTorrent (/) (в основном они написаны на Python) делают это.

Преимущество распространения кода таким способом в том, что ваше приложение будет работать независимо от того, установлена ли на компьютере пользователя требуемая (или хоть какая-нибудь) версия Python. В Windows и для многих дистрибутивов Linux и OS X корректная версия Python не установлена заранее. Помимо этого, программное обеспечение конечного пользователя всегда должно иметь исполняемый формат. Файлы с расширением .py предназначены для программных инженеров и системных администраторов.

Недостаток у заморозки один — она увеличивает размер вашего дистрибутива на 2–12 Мбайт. Кроме того, вам придется отправлять обновленные версии вашего приложения, когда будут выходить обновления безопасности к Python.

Проверяем лицензии при использовании библиотек, написанных на C

Вы должны проверять лицензии для каждого пакета, который используете, на всех уровнях дерева зависимостей. Но мы особенно хотели бы обратить ваше внимание на Windows, поскольку всем решениям для этой операционной системы требуются динамически подключаемые библиотеки (dynamically linked libraries, DLL), написанные на MS Visual C++ и установленные на целевой машине. У вас может не быть разрешения распространять некоторые библиотеки, поэтому вы должны проверять свои возможности перед распространением приложения (см. сообщение Microsoft () о файлах Visual C++ для получения более подробной информации). Опционально вы можете использовать компилятор MinGW (/) (расшифровывается как Minimalist GNU for Windows), но, поскольку это проект GNU, лицензия может быть ограничительной (всегда должна быть открытой и бесплатной).

Кроме того, компиляторы MinGW и Visual C++ не полностью похожи друг на друга, поэтому вы должны проверить, работают ли ваши юнит-тесты так, как вы того ожидаете, после использования другого компилятора. Мы начинаем отходить от основной темы, поэтому проигнорируйте все, что здесь написано, если вы нечасто компилируете код C для Windows, но, например, все еще могут возникнуть кое-какие проблемы при использовании MinGW и NumPy (). В «Википедии» для NumPy есть статья (), в которой рекомендуется применять сборки MinGW со статическими наборами инструментов.

Мы сравним популярные инструменты для заморозки в табл. 6.1. Все они взаимодействуют со стандартной библиотекой Python. Они не могут выполнять кросс-платформенную заморозку, поэтому вы должны проводить сборки на целевых платформах.

Инструменты перечислены в том порядке, в каком описаны в этом разделе. PyInstaller и cx_Freeze могут использоваться на всех платформах, py2app работает только для OS X, py2exe — только для Windows, а bbFreeze может работать на UNIX-подобных системах и для Windows, но не для OS X (он еще не портирован на Python 3). Он может генерировать архивы egg, если вам нужна такая функциональность для вашей легаси-системы.

Таблица 6.1. Инструменты для заморозки

 

pyInstaller

cx_Freeze

py2app

py2exe

bbFreeze

Python 3

Да

Да

Да

Да

Лицензия

Модифицированная GPL

Модифицированная PSF

MIT

MIT

Zlib

Windows

Да

Да

Да

Linux

Да

Да

Да

OS X

Да

Да

Да

Eggs

Да

Да

Да

Да

Поддержка pkg_resources*

Да

Да

Режим одного файла**

Да

Да

* pkg_resources () — это отдельный модуль, поставляющийся с Setuptools, который может использоваться для автоматического поиска зависимостей. При заморозке кода возникают трудности, поскольку сложно вручную находить динамически загруженные зависимости статического кода. PyInstaller, например, только говорит о том, что все будет хорошо, когда анализ проводится для egg-архива.

** Режим одного файла — это способ размещения пакетов приложения и всех его зависимостей в едином исполняемом файле в ОС Windows. InnoSetup () и Nullsoft Scriptable Install System (NSIS) () — это популярные инструменты для создания установщиков, которые могут объединять код в единый файл с расширением .exe.

PyInstaller

PyInstaller (/) может быть использован для создания приложений для OS X, Windows и Linux. Его основное предназначение — быть совместимым со сторонними пакетами после установки, поэтому заморозка сразу работает. По адресу перечислены пакеты, поддерживаемые PyInstaller. Список поддерживаемых графических библио­тек содержит Pillow, pygame, PyOpenGL, PyGTK, PyQT4, PyQT5, PySide (за исключением надстроек для Qt) и wxPython. Поддерживаются также инструменты NumPy, Matplotlib, Pandas и SciPy.

PyInstaller имеет модифицированную лицензию GPL () «с особым исключением, которое позволяет [всем] использовать PyInstaller для сборки и распространения небесплатных программ (включая коммерческие)», поэтому лицензии, которым вы должны подчиняться, будут зависеть от используемых вами при разработке кода библиотек. Команда разработчиков PyInstaller даже предоставляет инструкции, как спрятать исходный код (), для тех, кто создает коммерческие приложения или хочет, чтобы никто не изменял их код. Обязательно прочтите текст лицензии (проконсультируйтесь с адвокатом, если это важно, или воспользуйтесь ресурсом /, если это неважно), если вам нужно модифицировать их исходный код для того, чтобы создать собственное приложение, поскольку вам, возможно, придется поделиться изменениями.

Руководство к PyInstaller (/) содержит достаточно информации. Взгляните на страницу , где приводятся требования для PyInstaller, чтобы убедиться, что ваша система совместима: для Windows вам потребуется версия XP или выше, для систем Linux — несколько консольных приложений (списки документации, где вы можете их найти), а для OS X — версия 10.7 (Lion) или выше.

Вы можете использовать Wine (эмулятор Windows) для кросс-компиляции для Windows при работе с Linux или OS X.

Чтобы установить PyInstaller, используйте pip из той виртуальной среды, из которой будете строить ваше приложение:

$ pip install pyinstaller

Для создания стандартного исполняемого файла из модуля script.py введите следующую команду:

$ pyinstaller script.py

Для создания оконного приложения для OS X или Windows задайте флаг --windowed в командной строке:

$ pyinstaller --windowed script.spec

Появляются две новые папки и файл в том же каталоге, где вы выполнили команду pyinstaller:

файл с расширением .spec, который можно запустить с помощью PyInstaller для повторного создания сборки;

• каталог сборки, в котором хранятся некоторые файлы журнала;

каталог dist, в котором хранятся главный исполняемый файл и некоторые зависимые библиотеки Python.

PyInstaller помещает все библиотеки Python, используемые вашим приложением, в каталог dist, поэтому, когда начнете распространять исполняемый файл, не забудьте, что вы должны распространять весь каталог dist.

Файл script.spec можно изменить для того, чтобы настроить сборку (). Вы можете сделать следующее:

связать файлы данных и исполняемые файлы;

• включить библиотеки времени выполнения (файлы с расширением .dll или .so), которые PyInstaller не может определить автоматически;

добавить для исполняемого файла флаги времени выполнения Python.

Это полезно, поскольку теперь файл можно хранить с помощью системы контроля версий, что упрощает создание будущих сборок. Вики-страница PyInstaller содержит рецепты сборки () для некоторых распространенных приложений, включая Django, PyQt4, а также функционал по подписанию кода для Windows и OS X. Там же вы найдете последнюю версию руководства для PyInstaller. Теперь отредактированный файл script.spec можно запускать как аргумент для pyinstaller (вместо повторного использования script.py):

$ pyinstaller script.spec

13058.png

Когда PyInstaller предоставляют файл с расширением .spec, он берет все парамет­ры из содержимого этого файла и игнорирует параметры командной строки, за исключением следующих: --upx-dir=, --distpath=, --workpath=, --noconfirm, и --ascii.

cx_Freeze

Как и PyInstaller, cx_Freeze (/) может замораживать проекты Python для ОС Linux, OS X и Windows. Однако команда разработчиков cx_Freeze не рекомендует компилировать для Windows с помощью Wine, поскольку им пришлось вручную скопировать некоторые файлы, чтобы приложение работало. Для установки спользуйте pip:

$ pip install cx_Freeze

Самый простой способ создать исполняемый файл — запустить cxfreeze из командной строки, но есть и другие варианты (вы можете использовать систему контроля версий), если вы пишете сценарий setup.py.

Это тот же самый файл setup.py, что и для модуля distutils из стандартной библио­теки Python: cx_Freeze расширяет distutils таким образом, чтобы предоставлять несколько дополнительных команд (и модифицировать некоторые другие).

Данные параметры можно передавать через командную строку, сценарий установки или с помощью конфигурационного файла setup.cfg ().

Сценарий cxfreeze-quickstart создает простой файл setup.py, который может быть изменен и сохранен в системе контроля версий для будущих сборок. Рассмот­рим пример сессии для сценария с именем hello.py:

$ cxfreeze-quickstart

Project name: hello_world

Version [1.0]:

Description: "This application says hello."

Python file to make executable from: hello.py

Executable file name [hello]:

(C)onsole application, (G)UI application, or (S)ervice [C]:

Save setup script to [setup.py]:

Setup script written to setup.py; run it as:

    python setup.py build

Run this now [n]?

Теперь у нас есть сценарий установки и мы можем изменить его в соответствии с нуждами нашего приложения. Параметры вы можете найти в документации к cx_Freeze в разделе distutils setup scripts (). Существуют также пример сценария setup.py и работающие приложения с минимальной функциональностью, которые показывают, как замораживать приложения, использующие PyQT4, Tkinter, wxPython, Matplotlib, Zope и другие библиотеки. Вы можете найти их в каталоге samples/ исходного кода cx_Freeze (): перейдите из каталога высшего уровня в cx_Freeze/cx_Freeze/samples/. Код также поставляется с установленной библиотекой. Вы можете получить путь, введя следующую команду:

$ python -c 'import cx_Freeze; print(cx_Freeze.__path__[0])'

Когда закончите редактировать файл setup.py, можете использовать его для создания собственного исполняемого файла с помощью одной из этих команд:

13070.png 

13075.png Этот параметр предназначен для создания исполняемого файла для командной строки.

13088.png Этот параметр модифицирован cx_Freeze, чтобы вы могли обрабатывать исполняемые файлы Windows и их зависимости.

13101.png Этот параметр модифицирован, чтобы вы могли гарантировать, что пакеты для Linux создаются с подходящей архитектурой для текущей платформы.

13112.png Этот параметр позволяет создать пакет для отдельного оконного приложения для OS X (.app), содержащий зависимости и исполняемый файл.

13124.png Этот параметр позволяет создать пакет app и пакет приложения, которые затем будут упакованы в образ диска DMG.

py2app

py2app () позволяет создать исполняемые файлы для OS X. Как и cx_Freeze, он расширяет distutils, добавляя новую команду py2app. Чтобы установить ее, используйте pip:

$ pip install py2app

Далее автоматически сгенерируйте сценарий setup.py с помощью команды py2applet:

$ py2applet --make-setup hello.py

Wrote setup.py

Вы создали простой файл setup.py, который можно модифицировать согласно вашим потребностям. Вы можете найти примеры работающих приложений с минимальной функциональностью и соответствующими сценариями setup.py, которые используют библиотеки вроде PyObjC, PyOpenGL, pygame, PySide, PyQT, Tkinter и wxPython в исходном коде py2app (/). Для этого перейдите из каталога верхнего уровня в каталог py2app/examples/.

Далее запустите файл setup.py с помощью команды py2app, чтобы создать два каталога — build и dist. Убедитесь, что вы очистили каталоги перед выполнением повторной сборки. Команда выглядит так:

$ rm -rf build dist

$ python setup.py py2app

Чтобы прочесть дополнительную документацию, обратитесь к руководству py2app (). Сборка может завершиться генерацией исключения AttributeError. Если это произошло, прочтите в руководстве об использовании py2app () — запись переменных scan_code и load_module, возможно, нужно начинать с нижнего подчеркивания: _scan_code и _load_module.

py2exe

py2exe () создает исполняемые файлы для Windows. Он очень популярен, клиент BitTorrent (/) для Windows был создан с помощью py2exe. Как и cx_Freeze и py2app, он расширяет distutils, в этом случае добавляется команда py2exe. Если вам нужно использовать его с Python 2, загрузите более старую версию py2exe из sourceforge (/). В противном случае (если у вас установлен Python 3.3+) используйте pip:

$ pip install py2exe

Руководство к py2exe () составлено превосходно (возможно, потому что документация размещена на вики-странице, а не в системе контроля версий). Самый простой сценарий setup.py выглядит так:

from distutils.core import setup

import py2exe

setup(

      windows=[{'script': 'hello.py'}],

)

В документации перечислены все параметры конфигурации для py2exe (), а также приведены детальные заметки о том, как (опционально) включить иконки () или создать единый исполняемый файл (). В зависимости от лицензии для Microsoft Visual C++ у вас может быть (или не быть) возможность распространять библиотеки среды выполнения для Microsoft Visual C++ вместе с вашим кодом. Если вам это доступно, изучите инструкции по распространению DLL Visual C++  вместе с исполняемыми файлами; в противном случае вы можете предоставить пользователям вашего приложения способ загрузить и установить Microsoft Visual C++ 2008 redistributable packge () или Visual C++ 2010 redistributable packge (), если вы используете Python 3.3 или выше.

После того как вы подкорректируете свой файл установки, можете сгенерировать исполняемый файл в каталог dist, введя следующую команду:

$ python setup.py py2exe

bbFreeze

Библиотеку bbFreeze () в данное время никто не поддерживает, и она не была портирована на Python 3, но ее все еще часто загружают. Как и библиотеки cx_Freeze, py2app и py2exe, она расширяет модуль distutils, добавляя команду bbfreeze. Фактически более старые версии bbFreeze были основаны на cx_Freeze. Эта библиотека может пригодиться тем, кто поддерживает легаси-системы и хотел бы упаковывать сборки в архивы egg, чтобы затем использовать их в своей инфраструктуре. Для установки используйте команду pip:

$ pip install bbfreeze  # bbFreeze can't work with Python3

Для нее практически нет документации, но вы можете найти алгоритмы сборки () для Flup (), Django, Twisted, Matplotlib, GTK и Tkinter, а также многие другие. Чтобы создать исполняемые бинарные файлы, используйте команду bdist_bbfreeze следующим образом:

$ bdist_bbfreeze hello.py

Она создаст каталог dist по адресу, где была запущена bbfreeze, в этом каталоге будут находиться интерпретатор Python и исполняемый файл с таким же именем, что и сценарий (в нашем случае hello.py).

Для того чтобы сгенерировать архив egg, используйте новую команду distutils:

$ python setup.py bdist_bbfreeze

Существуют и другие варианты, например разметка сборок как снепшотов или ежедневные сборки. Для того чтобы получить больше информации об использовании библиотеки, воспользуйтесь флагом --help:

$ python setup.py bdist_bbfreeze --help

Для более тонкой настройки задействуйте класс bbfreeze.Freezer (этот способ использования bbfreeze предпочтительный). Он имеет флаги, которые указывают, применять ли сжатие в созданном ZIP-файле, включать ли интерпретатор Python, а также какие сценарии выбрать.

Упаковка дистрибутивов в Linux

Создание дистрибутивов в ОС Linux — это, возможно, «правильный способ» распространения кода для Linux: built distribution похож на замороженный пакет, но не содержит интерпретатор Python, поэтому размер файла меньше примерно на 2 Мбайт по сравнению с замороженным. Если для дистрибутива выходит новое обновление безопасности для Python, ваше приложение автоматически начнет использовать эту версию Python.

Команда bdist_rpm из модуля distutils стандартной библиотеки Python позволяет легко создать файл RPM () для использования в дистрибутивах Linux вроде Red Hat или SuSE.

Подводные камни при создании пакетов дистрибутивов в Linux

Создание и поддержка разных конфигураций, необходимых для каждого формата дистрибутива (например, *.deb для Debian/Ubuntu, *.rpm для Red Hat/Fedora, и т. д.), потребует много усилий. Если ваш код — это приложение, которое вы планируете распространять на других платформах, вам также придется создать отдельную конфигурацию, необходимую для заморозки приложения в Windows и OS X. При создании и поддержке одного конфигурационного файла для любого из кросс-платформенных инструментов заморозки, описанных в разделе «Замораживаем код» ранее (это создаст отдельные исполняемые файлы для Windows, OS X и всех дистрибутивов Linux), нужно выполнить куда меньше работы.

Создание пакета дистрибутива также проблематично, если ваш код предназначен для той версии Python, которая в данный момент не поддерживается дистрибутивом. Вам придется сказать пользователям некоторых версий Ubuntu, что им нужно добавить кое-какой функционал с помощью команд sudo apt-repository перед установкой ваших файлов с расширением .deb (а это ухудшает мнение о программе). Помимо этого, вам придется поддерживать эквиваленты этих инструкций для каждого дистрибутива и, что еще хуже, обязать пользователей прочитать их и действовать в соответствии с ними.

Обратите внимание на ссылки, которые предоставляют инструкции по упаковке кода Python для некоторых популярных дистрибутивов Linux:

Fedora ();

• Debian и Ubuntu ();

Arch ().

Если хотите оперативно упаковывать код для всех разновидностей Linux, можете попробовать приложение effing package manager (fpm) (). Оно написано на Ruby и языке оболочки, но нравится нам, поскольку упаковывает код из нескольких источников (включая Python) в файлы для Debian (.deb), RedHat (.rpm), OS X (.pkg), Solaris и других ОС. Оно также позволяет ускорить работу, но не предоставляет дерево зависимостей, поэтому те, кто поддерживает пакет, могут отнестись к нему с неодобрением. Пользователи Debian могут попробовать Alien (/) — написанную на Perl программу, которая преобразует файлы между форматами Debian, RedHat, Stampede (.slp) и Slackware (.tgz), но ее код не обновлялся с 2014 года, и те, кто его поддерживал, уже не занимаются этим.

Для тех, кому интересно, Роб МакКуин (Rob McQueen) разместил свои мысли о развертывании серверных приложений при работе в ОС Debian ().

Исполняемые ZIP-файлы

Мало кто знает, что Python может выполнять ZIP-файлы, содержащие файл __main__.py, начиная с версии 2.6. Это отличный способ упаковки приложений, написанных на чистом Python (приложений, которым не нужны бинарные файлы для указанных платформ). Поэтому, если у вас есть отдельный файл __main__.py примерно такого содержания:

if __name__ == '__main__':

    try:

        print 'ping!'

    except SyntaxError:  # Python 3

        print('ping!')

и вы создаете ZIP-файл, содержащий его, введите следующую команду:

$ zip machine.zip __main__.py

Вы сможете отправить этот ZIP-файл другим пользователям; и, если у них установлен Python, они могут выполнить его в командной строке следующим образом:

$ python machine.zip

ping!

Если хотите создать исполняемый файл, можете добавить в начало ZIP-файла POSIX символы #! (называется shebang — «шебанг») — формат ZIP это позволяет, — и у вас получится независимое приложение (если Python доступен по пути, указанном с помощью последовательности символов #!). Рассмотрим пример, который продолжает предыдущий код:

$ echo '#!/usr/bin/env python' > machine

$ cat machine.zip >> machine

$ chmod u+x machine

А теперь его исполняемый файл:

$ ./machine

ping!

13162.png

Начиная с Python 3.5 в стандартной библиотеке существует модуль zipapp (), который позволяет создавать ZIP-файлы более удобным способом. Он также добавляет гибкости, поэтому основной файл не должен обязательно называться __main__.py.

Если вы используете сторонние зависимости, размещая их в текущем каталоге, и изменяете оператор импорта, можете создать исполняемый ZIP-файл, который будет содержать все зависимости. Если структура каталогов выглядит так:

.

|--- archive/

     |--- __main__.py

и вы работаете в виртуальной среде, где установлены только необходимые вам зависимости, вы можете ввести следующие команды в оболочке, чтобы включить ваши зависимости:

$ cd archive

$ pip freeze | xargs pip install --target=packages

$ touch packages/__init__.py

Команда xargs принимает стандартный вывод от pip freeze и превращает его в список аргументов команды pip, флаг --target=packages отправляет установку в новый каталог packages. Команда touch создает пустой файл, если таких не существует. В противном случае обновляет временную метку, устанавливая ее значение равным текущему времени. Структура каталога будет выглядеть так:

.

|--- archive/

     |--- __main__.py

     |--- packages/

          |--- __init__.py

          |--- dependency_one/

          |--- dependency_two/

Убедитесь, что вы изменяете оператор импорта для использования каталога packages, который только что создали:

#импортируем dependency_one  # не эту

import packages.dependency_one as dependency_one

А затем рекурсивно включите все каталоги в новый ZIP-файл с помощью команды zip -r, например так:

$ cd archive

$ zip machine.zip -r *

$ echo '#!/usr/bin/env python' > machine

$ cat machine.zip >> machine

$ chmod ug+x machine

Ходят слухи (), что они предпочитают называть себя «министерством установки». Ник Коглан (Nick Coghlan), назначенный BDFL для работы с PEP, связанными с упаковкой, написал в своем блоге содержательную статью о самой системе, ее истории и направлении развития ().

На данный момент существуют два URL, которые ссылаются на одинаковое содержимое: / и .

В данный момент постепенно осуществляется переход от PyPI к Warehouse (/) (находится на стадии оценки). Мы можем сказать, что изменился пользовательский интерфейс, но не API. Если вам любопытно, Николь Хэррис (Nicole Harris), один из разработчиков PyPA, написала краткое введение к Warehouse (/).

Если у вас установлен Python 3.4 или выше, но нет pip, вы можете установить его из командной строки с помощью команды python —m ensurepip.

Заморозка кода Python на Linux с его преобразованием для выполнения в ОС Windows применялась в PyInstaller 1.4, но от этой возможности отказались в версии 1.5 (), поскольку она работала только для программ, написанных на чистом Python (то есть не для графических приложений).

Как мы увидим при взгляде на другие установщики, сложность заключается не в поиске и объединении в пакеты совместимых библиотек, написанных на C, необходимых для определенной версии библиотеки Python, а в обнаружении периферических файлов конфигурации, спрайтов или особой графики, а также других файлов, которые не обнаруживает инструмент для заморозки при исследовании вашего исходного кода.

Некоторые могли слышать, как их называют бинарными пакетами или установщиками; в Python они имеют официальное имя «дистрибутивы», которое означает RPM, пакеты Debian или исполняемые установщики для Windows. Формат wheel также является разновидностью дистрибутива, но по разным причинам, которые рассматриваются в статье, посвященной wheels, зачастую лучше создавать дистрибутивы для отдельных платформ Linux (), как показано в этом разделе.

Назад: 5. Читаем отличный код
Дальше: Часть III. Руководство по сценариям