• en
  • Language: ru
  • Documentation version: latest

24. Нацеливание на Python 2+3

Во многих случаях вам может понадобиться разрабатывать программы, которые можно запускать как в Python 2+, так и в Python 3+.

Представьте, что у вас есть очень популярный модуль Python, которым пользуются сотни людей, но не у всех из них одинаковая версия Python (2 или 3). В этом случае у вас есть два варианта. Первый - распространить два модуля, один для Python 2, а другой для Python 3. Другой вариант - модифицировать ваш текущий код и сделать его совместимым с Python 2 и 3.

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

Будущий импорт

Первый и самый важный метод - это использование импорта __future__. Он позволяет импортировать функциональность Python 3 в Python 2. Вот несколько примеров:

Контекстные менеджеры появились в Python 2.6+. Для их использования в Python 2.5 вы можете использовать:

from __future__ import with_statement

В Python 3 функция print была заменена на функцию. Если вы хотите использовать ее в Python 2, вы можете импортировать ее из __future__:

print
# Output:

from __future__ import print_function
print(print)
# Output: <built-in function print>

Разбираемся с переименованием модулей

Во-первых, скажите, как вы импортируете пакеты в свой скрипт? Большинство из нас делают это:

import foo
# or
from foo import bar

Знаете ли вы, что вы тоже можете сделать нечто подобное?

import foo as foo

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

try:
    import urllib.request as urllib_request  # for Python 3
except ImportError:
    import urllib2 as urllib_request  # for Python 2

Итак, позвольте мне немного объяснить приведенный выше код. Мы оборачиваем наш код импорта в предложение try/except. Мы делаем это потому, что в Python 2 нет модуля urllib.request, поэтому в результате получится ImportError. Функциональность urllib.request обеспечивается модулем urllib2 в Python 2. Поэтому при использовании Python 2 мы пытаемся импортировать urllib.request и если получаем ImportError, то говорим Python импортировать urllib2 вместо этого.

Последнее, о чем вам нужно знать, это ключевое слово as. Оно отображает импортируемый модуль на urllib_request. Таким образом, все классы и методы из urllib2 доступны нам через псевдоним urllib_request.

Устаревшие встроенные модули Python 2.

Еще один момент, о котором следует помнить: 12 встроенных модулей Python 2 были удалены из Python 3. Убедитесь, что вы не используете их в Python 2, чтобы сделать ваш код совместимым с Python 3. Вот способ заставить вас отказаться от этих 12 встраиваемых модулей и в Python 2:

from future.builtins.disabled import *

Теперь при попытке использовать модули, от которых отказались в Python 3, возникает ошибка NameError, как показано ниже:

from future.builtins.disabled import *

apply()
# Output: NameError: obsolete Python 2 builtin apply is disabled

Внешние бэкпорты стандартных библиотек.

В природе существует несколько пакетов, которые обеспечивают функциональность Python 3 в Python 2. Например:

  • перечисление pip install enum34

  • singledispatch pip install singledispatch.

  • pathlib pip install pathlib

Для дальнейшего чтения в документации по Python есть comprehensive guide шагов, которые необходимо предпринять, чтобы сделать ваш код совместимым с Python 2 и 3.