Может ли от __future__ импортировать... гарантировать совместимость Python 2 и 3?
Мне не интересно разогревать "Python 2 или Python 3?" (хотя самый последний из них, который я нашел, старше одного года), но я наткнулся на это выражение:
Вы можете написать код Python 3 под Python 2, если ваш файл начинается с линией:
from __future__ import absolute_import, division, generators, unicode_literals, print_function, nested_scopes, with_statement
С этой строкой ваш код будет работать с Python 2 или Python 3. Там могут быть редкие случаи, когда он не работает, но у меня есть не найден,
Это правда? Является ли эта единственная строка достаточной для того, чтобы код, который вы пишете, выполнялся как на Python 2.x( >= 2.5, я предполагаю), так и на 3.x(если предполагается, что импортированные модули доступны в обоих)?
Ответы
Ответ 1
"Это зависит от
Нет: Добавление этих импортных данных в код Python 2 не приведет к запуску под Python 3.
Да:. При наличии этих данных вы можете писать код, который работает как под Python 2, так и с Python 3.
Но: опять же, вы можете сделать это без этих импортных операций, а некоторые из них, например unicode_literals
, оказались просто не полезными. generators
и with_statement
не имеют ничего общего с Python 2 на Python 3, это функции, добавленные в версии Python 2.
Итак, в заключение, эти импорты - это немного красная селедка, и утверждение более ошибочно, чем право.
Однако, что не означает, что писать код, который работает как под Python 2, так и с Python 3, невозможно или даже обязательно очень сложно. Подробнее см. http://python3porting.com/.
Ответ 2
Я бы сказал, что нет, это балони. Даже при импорте все еще существуют существенные различия между Python 2 и 3: например, input()
в Python 3 похож на raw_input()
в Python 2; range()
в Python 3 похож на xrange()
на Python 2. В случае xrange()
вам, вероятно, удастся избежать использования range()
в Python 2, если диапазоны невелики, но если они большие, ваша программа может иметь очень различное использование памяти в Python 2 и Python 3.
В код можно добавить что-то вроде этого:
try:
range = xrange
input = raw_input
except NameError:
pass
Но тогда вам нужно найти все эти крайние случаи и исправить их. Например, существуют методы keys()
и values()
dict
, которые возвращают итераторы в Python 3, но списки в Python 2, поэтому вам нужно написать подкласс dict
, который "исправляет" это (и затем никогда не используйте словарные литералы в своем коде, не обертывая их, поскольку в противном случае они имели бы встроенный тип dict
).
Я полагаю, что, используя __future__
и различные исправления, и ограничивая себя написанием кода в подмножестве Python, созданного таким образом, который будет работать под 2.x и 3.x, возможно, напишите код, который выполняется в обеих версиях. Похоже, что много работы. Там есть причина, когда утилита 2to3
...
Ответ 3
Это не невозможно, в зависимости от требований вашей кодовой базы. Вероятно, вы найдете библиотеку six (2 * 3, ха-ха); другим полезным инструментом является python-modernize, который пытается преобразовать ваш код в состояние кросс-совместимости.
Ответ 4
Это сделает его более вероятным, но есть некоторые вещи, которые не могут быть получены из импорта __future__
, и некоторые вещи, которые удаляются в 3.x.
Сверху моей головы вы все равно можете использовать распаковку параметров tuple, которая удаляется в 3.x, и вы не сможете использовать красивую распаковку со звездообразным оператором, который вводится в 3.x.
например:
def some_function((x, y), magnitude): #This has been removed in 3.x
pass
x, *y = (1, 2, 3) #This does not exist in 2.x
Тем не менее, с некоторой осторожностью, чтобы избежать таких вещей, вы можете определенно написать код, который работает в обеих версиях, да.
Очевидно, что это относится только к версиям 2.x, в которых есть встроенные в них функции. Из-за этого некоторые из этой строки на самом деле совершенно бессмысленны - например, нет причин для импорта generators
, поскольку любая версия, которая может импортировать оператор with, уже будет иметь генераторы, работающие как стандартные. То же самое касается nested_scopes
.
В общем, я рекомендую просто писать для 3.x - нет никаких препятствий для установки обеих версий обеих версий. Если вам действительно нужна поддержка 2.x, напишите для 2.x столько функций, сколько вы хотите, и используйте 2to3 для очистки всего остального.
Ответ 5
Нах. Другие отметили некоторую разницу, есть и другие. Один из самых фундаментальных заключается в том, что родные строки Python 3 являются многобайтными - это вызывает проблемы при общении с однобайтовыми механизмами, такими как каналы для других процессов. Другие включают переименование модулей (Tkinter to tkinter), True и False - теперь ключевые слова.
Даже сравнение может быть не таким, следующий неправильный код:
num = 42
txt = "3"
if txt < num:
print ('Wow!')
else:
print ('Doh!')
создает a TypeError
на Py3, но не на Py2.
Распаковка была упомянута. методы словаря items()
, keys()
и values()
объекты обратного просмотра (разные имена методов используются в версии 2.7). В итераторах Py3 используются больше, например, возвращаются из map()
и filter()
и т.д....
Ответ 6
Вы можете использовать будущий пакет: pip install future
In [1]: range(10)
Out[1]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [2]: from future.builtins import range
In [3]: range(10)
Out[3]: range(0, 10)
Вот их чит-лист с большим количеством примеров: http://python-future.org/compatible_idioms.html