blog.lorien.name
Распространение python приложений

Пишу кратко, без соплей :) Итак, есть какое-то python приложение, мы хотим, чтобы его можно было ставить через easy_install или pip. Например, это некий веб-фреймворк и лежит он в каталоге /web/foo т.е. пакет foo, а в нём всякие веб-вкусности, составляющие основу нашего фреймворка.

Для начала переместим /web/foo в /web/foo/foo, теперь наш проект будет лежать там, а /web/foo будет являться корнем распространяемого приложения, будет содержать документацию и служебную информацию, описывающую приложение.

Далее нужно создать файл /web/foo/setup.py. В этом файле хранится информация о структуре приложения, его название, описание, имя автора и прочие штуки. Подробности можно узнать в официальной документации по distutils - это стандартная библиотека языка python. Итак, пример файла setup.py: http://dumpz.org/22355/. Скачиваете этот файл, заменяете все строки foo на название вашего пакета. Обратите внимание, что я там ручками собираю список файлов для того, чтобы указать его в опции data_files. Если этого не сделать, то в финальный архив попадут только python-файлы. HTML файлов, css, картинок и прочих вещей там не будет. Если можно этот момент решить проще, скажите мне как, буду рад узнать. Теперь этот файл (setup.py) позволит нам создать архив для распространения. Пользовать может скачать архив, распаковать его и вызывать команду `python setup.py install` (да-да, это тот setup.py, который мы сейчас сделали) и эта команда установит приложение в систему.

Давайте, создадим ещё парочку файлов.

Файл LICENSE - здесь мы опишем по какой лицензии распространяется приложение, собственно это и есть текст лицензии. Я показываю пример для BSD лицензии.

Файл MANIFEST.in - честно говоря, забыл, что оно делает. Но оно нужно ;-) Не забудьте, заменить foo на имя вашего пакета.

Файл README - чиркните пару слов, что делает ваше приложение, куда слать багрепорты, благодарности, проклятия, деньги.

Ещё я файл AUTHORS обычно создаю и пишу туда себя любимого :o) Типа такого: AUTHORS

Так, проверяйте, у вас должна получиться такая структура файлов:

/web/foo
- setup.py
- MANIFEST.in
- README
- AUTHORS
- LICENSE
- foo (а это собственно сам пакет с исходными кодам) 

Отлично, теперь запускайте команду python setup.py register sdist upload. Register зарегает ваше приложение в Python Package Index, так что оно будет доступно через поиск на сайте http://pypi.python.org, sdist создаcт архив с вашим приложением, который можно распространять, а upload зальёт этот архив на pypi. Последний шаг очень важный - это позволит устанавливать приложение простой командой easy_install.

Обратите внимание, что вам также понадобится изменить структуру вашего репозитория т.к. появляется дополнительная родительская категория с файлом setup.py Кроме того вам будет нужно настроить список игнорируемых файлов. Добавить туда несколько служебных директорий, которые создаются в процессе выполнения команды python setup.py sdist.

Вот вам живой пример .hgignore из пакета django-common

Вот и всё.

Сейчас ещё популярен способ установки пакетов внутрь virtualenv с помощью pip непосредственно из репозитория. Чтобы это делать, вам всё равно необходимо создать файл setup.py, регистрировать приложение в Python Package Index не обязательно. Т.е. стуктура вашего приложения, файл setup.py - должны быть такими, как я описал выше - независимо от того, будете ли вы использовать easy_install или pip.

Ищем freelance проекты с помощью Yahoo Pipes

Оказывается, yahoo pipes кроме эстетического удовольствия составления алгоритма из визуальных кусочков, приносят ещё и практическую пользу :) На днях сделал трубу, которая фильтрует поток проектов с freelance бирж на темы python, django, парсинг. Получилась такая страничка:

http://pipes.yahoo.com/pipes/pipe.info?_id=dcab10c7e16006c9ef7749cd3700cb4b

А вот исходники трубы:

http://pipes.yahoo.com/pipes/pipe.edit?_id=dcab10c7e16006c9ef7749cd3700cb4b

Далее. Оказалось, что на результаты трубы можно подписаться по email. В итоге, абсолютно на халяву я регулярно получаю сводку по нужным проектам себе на мыло :)

Утилита поиска на PyPI

Сделал консольную утилиту для поиска пакетов на Python Package Index. Устанавливается обычным образом: sudo easy_install pypi-tools. После установки пакета становится доступной команда pypi.

Пример использования:

$ pypi gravatar
    django-gravatar                - Gravatar Support in a Django Reusable Application
    gravatar                       - Gravatar generator. Includes all API parameters included in their documentation.
    tw.gravatar                    - inserts gravatar images
    tw.gravatar                    - inserts gravatar images  

Так можно посмотреть информацию о пакете:

$ pypi -s tw.gravatar
     name:                tw.gravatar
     summary:             inserts gravatar images
     version:             0.1a0dev-20100727
     author:              Nicolas Laurance
     author_email:        nicolas[dot]laurance<at>gmail.com
     keywords:            toscawidgets.widgets,gravatar
     classifiers:         Development Status :: 3 - Alpha
                          Environment :: Web Environment
                          Environment :: Web Environment :: ToscaWidgets
                          Framework :: TurboGears :: Widgets
    …

Доступен также поиск по различным свойствам из описания пакета. Пример поиска по email автора:

$ ./pypi —author_email lorien@lorien.name
    django-account                 - Django application for registration and authentication
    django-bookmarker              - Social bookmark linsk
    django-common                  - A number of useful django shortcuts and helpers
    …

Страница проекта на pypi: http://pypi.python.org/pypi/pypi-tools/
Исходный код:  http://bitbucket.org/lorien/pypi-tools

Прожорливый djapian

Djapian - это django-приложение, разработанное Александром Кошелевым, упрощающее использование поискового движка xapian в django-сайтах.

В официальном tutotiral можно посмотреть примеры использования приложения, в том числе пример пагинации. Обратите внимание на вызов метода prefetch(). Поиск работает так, что в начале ищутся id объектов в индексном файле djapian, а затем уже по этим id достаются реальные объекты из базы данных т.е. djapian возвращает обыкновенный queryset. Так вот prefetch нужен для того, чтобы вытаскивать все объекты за раз одним запросом, иначе при итерации по результатам поиска на каждый объект будет сделан запрос. Проблема в том, что все объекты вытаскиваются ДО пагинации. Если результатам поиска удовлетворяют 200000 объектов, то они все будут извлечены из базы данных, несмотря на то, что после пагинации мы будем использовать лишь те объекты, что нужно отобразить на текущей странице поиска.

Если вы сталкивались с такой проблемой, интересно, как вы её решили. Я просто решил не использовать метод prefetch.