Как организовать модули Python для PyPI для поддержки 2.x и 3.x

У меня есть модуль Python, который я бы хотел загрузить в PyPI. Пока что он работает для Python 2.x. Теперь не должно быть слишком сложно написать версию для 3.x.

Но после следующих рекомендаций по созданию модулей в этих местах:

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

  • 2.x
  • 2.6 (возможно, в качестве специального случая для использования нового API-интерфейса буфера)
  • 3.x

Как можно настроить модуль Python в PyPI, чтобы кто-то мог:

easy_install modulename

и он установит правильную вещь, использует ли пользователь 2.x или 3.x?

Ответы

Ответ 1

Я обнаружил, что setup.py для httplib2, кажется, имеет элегантный способ поддержки Python 2.x и 3.x. Поэтому я решил скопировать этот метод.

Задача состоит в создании единственного setup.py для дистрибутива пакета, который работает со всеми поддерживаемыми дистрибутивами Python. Затем с тем же setup.py вы можете сделать:

python2 setup.py install

а также

python3 setup.py install

Должно быть возможно достаточно, чтобы setup.py был достаточно прост для анализа всех поддерживаемых дистрибутивов Python. Я успешно сделал это с пакетом cobs, который поддерживает от 2,4 до 2,6, а также 3.1. Этот пакет включает в себя чистый код Python (отдельный код для Python 2.x и 3.x) и расширения C, написанные отдельно для 2.x и 3.x.

Для этого:

1) Я поместил код Python 2.x в подкаталог python2 и код Python 3.x в подкаталог python3.

2) Я поместил код расширения C для 2.x и 3.x в каталог src в разделе python2 и python3.

Итак, структура каталогов:

root
  |
  +--python2
  |     |
  |     +--src
  |
  +--python3
  |     |
  |     +--src
  |
  +--setup.py
  +--MANIFEST.in

3) В setup.py у меня были эти строки около вершины:

if sys.version_info[0] == 2:
    base_dir = 'python2'
elif sys.version_info[0] == 3:
    base_dir = 'python3'

4) В вызове setup я указал пакеты как обычно:

setup(
    ...
    packages=[ 'cobs', 'cobs.cobs', 'cobs.cobsr', ],

5) Я указал базовый каталог для кода Python с помощью опции package_dir (см. шаг 3 для base_dir):

    package_dir={
        'cobs' : base_dir + '/cobs',
    },

6) Для расширений C я дал путь:

    ext_modules=[
        Extension('cobs.cobs._cobs_ext', [ base_dir + '/src/_cobs_ext.c', ]),
        Extension('cobs.cobsr._cobsr_ext', [ base_dir + '/src/_cobsr_ext.c', ]),
    ],

Это было о нем для setup.py. Файл setup.py обрабатывается как Python 2.x, так и 3.x.

7) Наконец, если вы создаете исходный дистрибутив, используя:

python2 setup.py sdist

то он по умолчанию будет тянуть только файлы, которые специально необходимы для сборки для этого Python. Например. в приведенном выше случае вы должны получить файлы в python2 только в исходном дистрибутиве, но не в файлах под python3. Но для полного распространения источника вы хотите включить файлы как для 2.x, так и 3.x. Для этого создайте файл MANIFEST.in, содержащий следующее:

include *.txt
recursive-include python2 *
recursive-include python3 *

Чтобы увидеть, что я сделал, см. исходный код cobs на PyPI или BitBucket.

Ответ 2

Простейшим решением является использование одного источника.