Подтвердить что ты не робот

Python 2 и Python 3 с двойным развитием

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

Я сталкивался с проектами, которые запускают 2to3 или даже 3to2, как часть их сценария установки. Кажется, это очень распространенный способ. Однако, кажется, есть несколько разных способов сделать это. Я также сталкивался с распространением.

Существует также возможность написания кода Python 2/Python 3 для полиглота. Несмотря на то, что это кажется ужасной идеей, я заметил, что в последнее время я склонен писать код, более идиоматичный, как код Python 3, хотя я все еще использую его как Python 2. У меня такое чувство, что это помогает моему собственному переходу только тогда, когда наконец наступает день, и он не делает ничего для того, чтобы предложить или хотя бы помочь двойной поддержке.

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

Спасибо!

4b9b3361

Ответ 1

Вы должны проверить six, библиотеку, которая обеспечивает унифицированный интерфейс для разных вещей, которые отличаются между Python 2 и 3.

Ответ 2

По моему опыту, это зависит от типа проекта.

Если это библиотека или очень автономное приложение, то в Python 2.7 обычно разрабатывается общий выбор, позволяющий максимально избегать конструкций, устаревших в Python 3.x, и прибегать к автоматизированным тестам для выявления дыр, оставленных py2to3, которые вам придется исправить вручную.

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

Для обработки Unicode я нашел это видео PyCon 2012 очень информативным. Этот совет хорош как для Python 2.x, так и для 3.x: обрабатывать каждую строку, поступающую извне, как байты и конвертировать в unicode как можно быстрее, а выходные строки конвертировать в байты как можно позже. Есть еще одно очень информативное видео об обработке даты/времени.

[Обновить]

Это старый ответ. На сегодняшний день (2019) нет хорошего обоснования для запуска проекта с использованием Python 2.x, и есть несколько веских причин для переноса старых проектов на Python 3. 7+ и отказа от поддержки Python 2.x.

Ответ 3

По моему опыту лучше не использовать библиотеку типа six; Вместо этого у меня есть один compat.py для каждого пакета с только необходимым кодом, не похожим на подход Скотта Гриффитса. six также несет ответственность за поддержку давно ушедших версий Python: правда в том, что жизнь намного проще, когда вы соглашаетесь с тем, что Pythons <= 2.6 и <= 3.2 исчезли. В версии 2.7 есть функции поддержки backported, такие как .view* методы на dict, которые работают точно так же, как и их не префиксные версии на Python 3; и Python 3.3 с другой стороны поддерживает префикс u для строк unicode снова.

Даже для очень существенных пакетов модуль compat.py, который позволяет другому коду работать без изменений, может быть довольно коротким: вот пример из pika, что мои коллеги и я помогли сделать 2/3 полиглота. Pika - один из тех проектов, в которых действительно были запутанные внутренние компоненты, смешивающие unicode и 8-битные строки друг с другом, но теперь мы использовали его в производстве на Python 3 уже более 6 месяцев без проблем.


Другая важная вещь - всегда использовать следующие __future__ при разработке:

from __future__ import absolute_import, division, print_function

Я рекомендую использовать unicode_literals, потому что на обеих платформах есть строки, которые должны быть типа str. Если вы не используете unicode_literals, вы можете сделать следующее:

  • b'123' - это 8-битный строковый литерал
  • '123' имеет тип str на обеих платформах
  • u'123' - это правильный текст в Unicode на обеих платформах.

В любом случае, пожалуйста, не делайте 2to3 при установке/времени сборки пакета; некоторые пакеты, используемые для этого в прошлом - pip install для этих пакетов потребовалось несколько секунд на Python 2, но ближе к минуте на Python 3.

Ответ 4

Выберите 2 или 3, в зависимости от того, какой из ваших любимых ароматов, и сделайте так, чтобы он работал очень хорошо, с модульными тестами. Затем убедитесь, что эти тесты работают после запуска через py2to3 или py3to2. Лучше поддерживать одну версию кода.

Ответ 5

Мой личный опыт заключался в том, что проще писать код, который работает без изменений как в Python 2, так и 3, а не полагаться на скрипты 2to3/3to2, которые часто не могут получить правильный перевод.

Возможно, моя ситуация необычна, поскольку я делаю много с байтовыми типами, а у 2to3 есть сложная задача, которая преобразует их, но удобство использования одной базы кода перевешивает гадость наличия нескольких хаков в коде.

В качестве конкретного примера мой модуль bitstring был ранним преобразованием в Python 3, и тот же код используется для Python 2.6/2.7/3.x. Источник - это более 4000 строк кода, и этот бит мне нужен, чтобы заставить его работать для разных основных версий:

# For Python 2.x/ 3.x coexistence
# Yes this is very very hacky.
try:
    xrange
    for i in range(256):
        BYTE_REVERSAL_DICT[i] = chr(int("{0:08b}".format(i)[::-1], 2))
except NameError:
    for i in range(256):
        BYTE_REVERSAL_DICT[i] = bytes([int("{0:08b}".format(i)[::-1], 2)])
    from io import IOBase as file
    xrange = range
    basestring = str

ОК, это не очень, но это означает, что я могу написать 99% кода в хорошем стиле Python 2, и все модульные тесты по-прежнему передаются для одного и того же кода в Python 3. Этот маршрут не для всех, но это вариант для рассмотрения.

Ответ 6

Если вам нужна поддержка Python 2.5 или ранее, использование Distribute и интеграция 2to3, как правило, лучший способ. Но если вам нужно только поддерживать Python 2.6 или новее, я бы сделал код, выполняемый под Python 2 и Python 3 без преобразования. Я бы также использовал библиотеку six, чтобы сделать это проще.