2008-08-21

Распространение модулей Python (distutils)

Не секрет, что у Python существует огромная стандартная библиотека с кучей модулей. Но кроме нее, существует просто огроменная коллекция модулей в pypi (Python Package Index).
Однако многие начинающие разработчики сталкиваются с проблемой распространения своих модулей. Можно конечно записать их все в архив и дать пользователям точные инструкции, как все это устанавливать. Однако это неудобно как для пользователей, так и для самих разработчиков. В python у этой проблемы есть простое и элегантное решение - создание стандартных пакетов при помощи модуля distutils.

Для модуля distuils есть очень подробная дока под названием Distributing Python Modules, но для первого прочтения и решения проблемы по-быстрому она явно сложновата.

Итак, допустим у нас есть некий проект - библиотека PyFoo. Состоит она из двух файлов и классов: foo.py и bar.py (ну и разумеется пустого файла __init__.py).



foo.py:
#!/usr/bin/env python
""" PyFoo package, foo class """


class Foo:
    """ Make a foo """

    def foo(self):
        return "foo"

bar.py:
#!/usr/bin/env python
""" PyFoo package, bar class """


class Bar:
    """ Make a bar """

    def bar(self, s):
        print '===', s, '==='

Итак, как же их наиболее удобно распространять?

Переносим их в директорию pyfoo.
А уровнем выше создаем файл setup.py:

#!/usr/bin/env python
""" Setup file for PyFoo package """

from distutils.core import setup
setup(name='pyfoo',
      version='1.2.3',
      description='PyFoo package',
      long_description = "PyFoo makes a foo",
      author='Vasya Pupkin',
      author_email='vasya@greenmice.info',
      url='http://greenmice.info/',
      packages=[ 'pyfoo', ],

      classifiers=(
          'Development Status :: 2 - Pre-Alpha',
          'Environment :: Console',
          'License :: OSI Approved :: GNU General Public License (GPL)',
          'Operating System :: POSIX',
          'Operating System :: Unix',
          'Programming Language :: Python',
        ),
      license="GPL-2"
     )

Я думаю тут все вполне понятно. Список принятых classifiers можно посмотреть на pypi.

Теперь достаточно сделать
python setup.py sdist
и просто магическим образом появляется директория dist с файлом pyfoo-1.2.3.tar.gz.

Теперь любому пользователю достаточно распаковать этот архив и сказать python setup.py install. Все файлы модуля окажутся там где им положено быть (например, в /usr/lib/python2.5/site-packages/pyfoo).

Ок. А что делать с исполняемыми файлами?

Создадим тестик к нашему пакажду (pyfoo_test.py):
#!/usr/bin/env python
""" PyFoo package test """

from pyfoo import foo, bar

f = foo.Foo()
b = bar.Bar()

print f.foo()
b.bar("Hello, world!")

И модифицируем setup.py следующим образом:
#!/usr/bin/env python
""" Setup file for PyFoo package """

from distutils.core import setup
setup(name='pyfoo',
      version='4.5.6',
      description='PyFoo package',
      long_description = "PyFoo makes a foo",
      author='Vasya Pupkin',
      author_email='vasya@greenmice.info',
      url='http://greenmice.info/',
      packages=[ 'pyfoo', ],
      scripts=['pyfoo_test.py'],

      classifiers=(
          'Development Status :: 2 - Pre-Alpha',
          'Environment :: Console',
          'License :: OSI Approved :: GNU General Public License (GPL)',
          'Operating System :: POSIX',
          'Operating System :: Unix',
          'Programming Language :: Python',
        ),
      license="GPL-2"
     )

Как видно, все очень лекго и удобно.
Для начала хватит, а если хочется большего - пожалуйте в документацию