Во многих случаях вам может понадобиться писать программы, которые будут корректно работать и на Python 2+ и на 3+.
Представьте, что у вас есть крайне популярный Python-пакет, который используют тысячи людей, но не у всех есть Python 2 или Python 3. В этом случае у вас есть два варианта. Первый - разрабатывать две версии параллельно, одну для второй ветки Python, а другую - для третьей. Другим вариантом будет изменение текущего кода для совместимости как с Python 2, так и с Python 3.
В данном разделе я собираюсь рассказать о нескольких приёмах, которые вы можете использовать, чтобы сделать скрипт совместимым с обоими ветками Python.
Первым и наиболее важным методом будет использование импорта __future__
.
Это позволяет вам импортировать функционал Python 3 в Python 2. Ниже несколько
примеров.
Менеджеры контекста были нововведением в Python 2.6+. Для их использования в Python 2.5 вам необходимо:
from __future__ import with_statement
print
стал функцией в Python 3. Для её использования в Python 2 вы можете
импортировать функцию из __future__
:
print
# Вывод:
from __future__ import print_function
print(print)
# Вывод: <built-in function print>
Для начала, скажите мне как вы импортируете модули в ваших скриптах? Большинство делает так:
import foo
# или
from foo import bar
А знаете ли вы про такой способ:
import foo as foo
Я знаю, что эффект будет такой же, как и в первом случае, но этот способ критичен для совместимости программ с Python 2 и 3. Попробуем следующий код:
try:
import urllib.request as urllib_request # для Python 3
except ImportError:
import urllib2 as urllib_request # для Python 2
Позвольте мне немного пояснить. Мы используем блок try/except
для импорта.
Причина - в Python 2 нет модуля urllib.request
, поэтому попытка его
импорта приведет к ImportError
. Функциональность urllib.request
доступна в модуле urlib2
в Python 2. Таким образом, при использовании
Python 2, при импорте urllib.request
мы упираемся в Exception и импортируем
urllib2
в качестве альтернативы.
Последнее что вам нужно знать - ключевое слово as
. С его помощью мы
импортируем модуль под именем urllib_request
. Дальше в коде мы просто
будем ссылаться на это имя, вне зависимости от того, какую ветку Python мы
используем.
В Python 2 есть 12 устаревших модулей, которые были удалены в Python 3. Для сохранения совместимости убедитесь, что не используете их в своем коде. Следующим образом можно явно запретить использование удаленного в Python 3 функционала:
from future.builtins.disabled import *
Теперь, при использовании удаленного в Python 3 модуля, мы будем получать
NameError
:
from future.builtins.disabled import *
apply()
# Вывод: NameError: obsolete Python 2 builtin apply is disabled
Существует несколько пакетов, которые предоставляют новый функционал Python 3 в Python 2. Например:
- enum
pip install enum34
- singledispatch
pip install singledispatch
- pathlib
pip install pathlib
В качестве дополнительного чтения: официальная документация содержит исчерпывающее руководство, объясняющее шаги, которые вам нужно предпринять для гарантии совместимости кода с обеими ветками Python.