Personal tools
You are here: Home Статьи Способы пакетирования модулей питона: обзор со стороны администратора
Document Actions

Способы пакетирования модулей питона: обзор со стороны администратора

by Ivan Fedorov last modified 2009-06-07 17:43

В статье описываются 2 примера велосипедостроения.

Много лет подряд модули для языка Python распространялись в основном в виде исходных кодов. Разработчиков модулей это не очень беспокоило, ибо проблемы пользователя редко волнуют рядового разработчика ПО. Тем более, что многие модули для языка Python выпускаются под открытыми лицензиями и разрабатываются на добровольных началах.

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

Отдельные разработчики иногда заботились о пользователях работающих на платформе Windows и выпускали для них бинарные сборки своих и иногда чужих модулей. В некоторые дистрибутивы Linux входил очень ограниченных набор собранных пакетов. Но реально проблема продолжала стоять достаточно остро.

И в это время появляется система setuptools, призванная решить эту проблему! Не правда ли полезное начинание?

Основная идея стоящая за setuptools – это сборка модулей в egg-архивы, которые собираются один раз и могут быть установлены на все системы. По сути дела egg – это zip-архив содержащий в себе каталог с модулем и каталог с мета-информацией. Гениальность такого подхода в том, что интерпретатор языка Python способен импортировать модули прямо из zip-архива, и поэтому для установки egg в систему даже не нужно распаковывать архив.

Пока все кажется прекрасно. Разработчики собирают свои модули в egg, пользователи их ставят. Но тут мы вспоминаем, что даже pure-Python модули скомпилированные для Python версии 2.4 не будут работать ни в версии 2.3, ни в версии 2.5. Эту проблему быстренько обошли, добавив в имя egg-архива суффикс «-pyX.Y», где X.Y – версия Python. Только мы решаем эту проблему, возникает проблема бинарных модулей для разных систем. Тут разработчики добавляют суффикс «-win32» к модулям собранным под системы семейства Windows и радуются. А вот что делать с десятками Linux'ов и различными BSD-клонами? А ещё есть как минимум Solaris и MacOS!

Вот и первая нерешённая проблема. Некоторые разработчики её решили добавив суффикс «-linux» для систем на базе Linux. Вспоминаем, что благодаря компании AMD у нас появилась возможность использовать на обычных компьютерах 64х-битные вычисления, но под 64х-битные системы нужны отдельные бинарные сборки. В том числе и под Windows-системы.

Проблема разных архитектур тоже не решена. Нет, в мета-информации есть поле «Platform», но пользы от него не шибко-то и много, ибо проверок никаких нет! Но допустим, что я использую только Linux и только на 32х-битных процессорах семейства x86. Тут выясняется, что включение оптимизации у компилятора делает модули неработоспособными на процессорах отличных от процессора, под который была оптимизация. Даже в такой, казалось бы стандартной ситуации, мы имеем проблемы. А ведь Linux-системы состоят из многих компонент. И основным компонентом любой Linux-системы, после ядра, является стандартная библиотека языка C, то есть «libc». И тут я не ошибся в написании, не «Glibc», а просто «libc». Существует множество различных реализаций стандартной библиотеки «libc». Например популярной во встраиваемых решениях реализацией является библиотека «uClibc». А проблема заключается в том, что модуль собранный с отличной от вашей реализацией библиотеки, не будет работать. И даже модуль собранный с другой версией вашей библиотеки может не заработать.

Так как минусов без плюсов не бывает, то поговорим о плюсах. Главный плюс для меня – это поддержка namespace-пакетов. Ничего особенного. Просто пустой пакет, который содержит в себе «__init__.py» и другие подпакеты. Главное, что это заметили в Zope Corporation, и теперь пилят свои модули на отдельные части!

Больше особо плюсов и нету, потому что все остальные возможности пользователю АБСОЛЮТНО безразличны в силу сложности их использования, а разработчики их могут легко реализовать и без setuptools.

Кто-нибудь может заметить про зависимости между egg. Так вот это вообще самое слабое место во всей реализации egg! Знаете откуда там берётся список зависимостей? Его РУКАМИ пишет разработчик. Большинство разработчиков не обновит однажды написанный файл зависимостей, до тех пор, пока в его почтовом количество жалоб от пользователей не начнёт составлять 90% почтового трафика! И они не сделают этого не потому, что они такие вредные, а потому, что это скучная и нудная работа, которая не приносит никакого удовлетворения! Поиск зависимостей должен быть автоматическим!

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

Начинаем ставить egg'и в систему и посмотрим на управление пакетами...

Так, а где у нас база установленных egg'ов? Что, нету? Надо лазить по PYTHONHOME и собирать инфу из кучи папок с мета-информацией? А периодами лезть прямо внутрь egg'ов? Потрясающе!

Ну ладно, руками я туда не полезу, пусть этим занимается setuptools. Для начала глянем, какие egg'и у нас уже установлены... а похоже что у setuptools нет такой функции... ну да это и не удивительно, трудно составить список пакетов без базы о них. Ладно, хрен с ним со списком.

Пусть просто обновит все установленные и пакеты... ага, оно и этого не может, хотя при установке может вытягивать зависимости из сети...

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

Господа, боюсь у нашего велосипеда не только колеса получились квадратными и разного размера, но и педали с цепью не соединены. Так что прошу всех слезть с велосипеда, взять его в руки и отправиться в пешее путешествие с велосипедами на руках! Только не надо его выкидывать, когда мы вернёмся назад с него можно будет снять несколько удачных деталей. Если не считать квадратных колес, неправильной сборки педального привода, и отсутствия некоторых важных деталей вроде руля и мягкого сиденья, то велосипед получился вполне неплохим!

И вот в такой не совсем радостной ситуации, после многих лет разработки сервера приложений Zope, компания Zope Corporation наконец-то поняла, что в мире Unix и Linux систем монолитный софт приживается с трудом. И решили они его разделить на компоненты, которые способны работать по отдельности. Прекрасное решение, заслуживающее всяческих похвал.

Но вместо того, чтобы разделить Zope на компоненты и дать её пользователям, они решили, что им тоже нужна своя система сборки. И в качестве базовой модели велосипеда они взяли setuptools и написали поверх него zc.buildout. Который по сути не решает никаких проблем setuptools.

У zc.buildout есть два преимущества перед чистым setuptools. Первое преимущество – набор «рецептов». Это некий расширяемый набор модулей для выполнения частых операций. И второе преимущество - бОльшая заточенность под особенности Zope.

Ну а недостатки zc.buildout прекрасно наследует от setuptools.

Я ещё не затронул тему вытягивания пакетов из сети... там где изобрести велосипед ещё имело смысл, его никто не стал изобретать. И та и другая система получают по протоколу HTTP HTML-страницу и разбирают её на части с помощью регулярных выражений. Я не противник регулярных выражений, скорее даже сторонник. Но не здесь! Здесь должен быть чётко определённых формат с подробным описанием имеющихся в сети пакетов. Например на основе XML. Ну да какой смысл делать этот формат, если описывать в нем НЕЧЕГО? Почему нечего? А потому что у egg не решены проблемы с зависимостями бинарных модулей!

А самое интересное, что никто из изобретателей этих велосипедов не обратил внимания на тот интересный факт, что почти все описанные здесь проблемы уже давно решены в большинстве дистрибутивов Linux. Где-то лучше, где-то хуже. Но РЕШЕНЫ. Давным давно были изобретены такие низкоуровневые пакетные менеджеры как rpm и dpkg. А над ними работают высокоуровневые apt и yum. Я мало работал с системами на основе dpkg, но вот с rpm я работал очень много.

Современные версии rpm автоматически определяют зависимости бинарных файлов от библиотек. В rpm заложена поддержка различных архитектур.

В дистрибутивах ALT Linux система сборки на основе rpm не только определяет зависимости бинарных модулей, но и ищет зависимости pure-Python модулей. Оно учитывает и архитектуру процессора, и стандартную библиотеку C-функций, и версию Python, и ещё кучу параметров. И это РЕАЛЬНО работает. Да, это решение ещё очень далеко от идеала, но это лучше чем ничего. namespace-пакеты в этой системе появились раньше, чем вышла первая версия setuptools! И ведь большая часть этой системы легкопортируемый pure-Python код! Остальное bash-код, который легко можно переписать на Python за несколько часов!

Так нафига было изобретать нежизнеспособные велосипеды, если было достаточно оглянуться по сторонам?

Вобщем egg-архивы должны остаться только на системах семейства Windows, и то, после того, как будут доработаны до состояния нормального менеджера пакетов с автоматическим поиском зависимостей.

С уважением, Ваш покорный слуга, который делает конфеты из материала заказчика. В данном случае из setuptools и zc.buildout.

Иркутск, 2007.02.21 02:55.


Powered by Plone CMS, the Open Source Content Management System