Разработка под Python 2+3 — Intermediate Python

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

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

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

Импорты Future

Первым и наиболее важным методом будет использование импорта __future__. Это позволяет вам импортировать функционал Python 3 в Python 2. Ниже несколько примеров.

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

from __future__ import with_statement

print стал функцией в Python 3. Для её использования в Python 2 вы можете импортировать функцию из __future__:

# Вывод:

from __future__ import print_function

print(print)

# Вывод: <built-in function print>

Переименование модулей

Для начала, скажите мне как вы импортируете модули в ваших скриптах? Большинство делает так:

import foo

from foo import bar

А знаете ли вы про такой способ:

import foo as foo

Я знаю, что эффект будет такой же, как и в первом случае, но этот способ критичен для совместимости программ с Python 2 и 3. Попробуем следующий код:

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

В 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.

Почему print(«Hello») работает в Python 2

Одним из самых заметных отличий Python 3 от Python 2 является разжалование print из инструкции языка (statement) до обычной функции.

Python 3:

# простое использование
print("Hello")
# выводит: Hello
# переданные аргументы по умолчанию объединяются через пробел
print("Hello", "world!")
# выводит: Hello world!
# объединяющий символ можно заменить на свой
print("Pythonic", "attacks!", sep="_")
# выводит: Pythonic_attacks!
# можно заменить символ конца строки на пустую строку,
# чтобы продолжить выводить что-нибудь в той же строке
print("Hello ", end="")
print("world!")
# выводит: Hello world!

Python 2:

# простое использование
print "Hello"
# выводит: Hello
# перечисленные аргументы объединяются через пробел
print "Hello", "world!"
# выводит: Hello world!
# если нужен не пробел, а другой символ для объединения,
# то остаётся делать только вот так:
print "_".join(["Hello", "world!"])
# выводит: Hello_world!
# можно при помощи запятой в конце избежать вывода \n (символа конца строки)
# и продолжить печатать что-нибудь на той же строке:
print "Hello",
print "world!"
# выводит: Hello world!
# если сделать специальный импорт из “будущего”, то
# в Python 2.
6+ `print` начинает работать как функция: from __future__ import print_function print("Hello", "world!") # выводит: Hello world!

Обычно инструкциями в Python являются только очень базовые вещи, такие как условия (if), циклы (for, while), возврат из функций (return) и т.д.

Преобразование print в функцию было сделано во имя упрощения синтаксиса языка. Инструкция

print для работы требовала значительного количества синтаксических конструкций, например, для отсутствия символа переноса строки (,) или перенаправления вывода в файл (>>). Всё это можно было заставить играть по общим правилам (и даже значительно расширить функционал) через позиционные и именованные аргументы функций, вообще без какого-либо расширения синтаксиса языка. Кроме того, print как функцию можно использовать гораздо гибче — например, фиксируя часть аргументов (каррирование) через functools. partial или использовать её в других функциях (передавать саму функцию как аргумент), типа
map()
или filter().

Недавно в исходниках библиотеки logging_tree я увидел, что print используется как функция без каких-либо импортов из будущего, при этом у библиотеки заявлена поддержка версий Python, начиная аж с 2.3:

print(build_description(node)[:-1])

Меня это удивило. Я даже создал пулл-реквест, будучи уверен, что нашёл ошибку. После того, как автор возразил, что к нему не поступало никаких жалоб по поводу такого использования print, я решил всё-таки проверить, как это работает. И к ещё большему моему удивлению, это и правда работало на всех версиях Python 2, до которых я смог дотянуться, включая 2.7, 2.6, 2.5, 2.4 и даже 2.3:

# как??
print("Hello")
# выводит: Hello

Немного поразмыслив и почитав, я осознал, где тут собака зарыта. Хоть это и выглядит как вызов функции print(), на самом деле это всё та же старая добрая инструкция print. Давайте разложим всё по полочкам:

# сначала отодвинем скобки от print, чтобы было нагляднее, что это инструкция:
print ("Hello")
# выводит: Hello
# в Python можно засунуть в скобки любое выражение, но пока оно там одно,
# то скобки не оказывают никакого влияния:
("Hello")
# получается просто строка: 'Hello'
# а если выражений несколько, или там есть запятая, то тогда уже
# создаётся кортеж:
("Hello",)  # кортеж из одного элемента
("Hello", "world")  # кортеж из двух элементов
# в нашем случае выражение только одно, поэтому скобки можно отбросить:
print "Hello"
# выводит: Hello

Как выяснилось, в Python 2 print и правда можно так, что со стороны это будет выглядеть как вызов функции, но для очень ограниченного множества случаев, а именно — должен быть только один позиционный аргумент. Такой код будет успешно выполняться и на Python 2 (благодаря описанному трюку), и на Python 3 (по-настоящему).

Разница становится очевидной, если попытаться узнать тип:

# у инструкций нельзя запросить тип, это синтаксически невозможно
>>> type(print)
  File "<stdin>", line 1
    type(print)
             ^
SyntaxError: invalid syntax
# а у функций можно
>>> from __future__ import print_function
>>> type(print)
<type 'builtin_function_or_method'>

Трюки из той же серии:

# условие со скобками как в C:
>>> if(1 == 1):
. ..     print("Equal!")
...
Equal!
# return как функция:
>>> def func():
...     return(True)
...
>>> func()
True

Это код синтаксически верен, но просто обычно так не пишут. И правильно.

Python 2.7 недавно получил свой последний релиз с исправлениями ошибок, и больше никогда не будет обновляться — даже новые найденные баги, связанные с безопасностью, не будут пофикшены. Хочется верить, что все заинтересованные уже обновились до Python 3, и никто больше активно не использует Python 2, в 2020-то году. К сожалению, вряд ли это так. Боюсь, что предсмертная агония Python 2 продлится ещё как минимум несколько лет. Поэтому знать про него хотя бы что-то всё равно полезно.

Благодаря этому случаю я узнал про странный трюк с print и извлёк урок, что нужно как минимум проверять свой фикс, прежде чем засылать куда-то пулл-реквест.

Если понравилась статья, то подпишитесь на уведомления о новых постах в блоге, чтобы ничего не пропустить!

  • Большой гайд про print на RealPython;
  • Брэтт Кэннон, «Why print became a function in Python 3″.

Обложка: Photo by mali maeder from Pexels

python — Использование print() (версия функции) в Python2.x

спросил

Изменено 5 лет, 2 месяца назад

Просмотрено 63к раз

Я понимаю разницу между оператором и выражением и понимаю, что Python3 превратил функцию print() в функцию.

Однако я запускал оператор print(), заключенный в круглые скобки, в различных интерпретаторах Python2.x, и он работал безупречно, мне даже не пришлось импортировать какой-либо модуль.

Мой вопрос: следующий код print("Hello SO!") оценивается как оператор или выражение в Python2.x?

  • python
  • печать
  • python-2.x
  • вызов функции

Рассмотрим следующие выражения:

 a = ("Hello SO!")
a = "Привет ТАК!"
 

Они эквивалентны. Точно так же с оператором:

 statement_keyword("foo")
оператор_ключевое слово "foo"
 

также эквивалентны.

Обратите внимание, что если вы измените функцию печати на:

 print("Hello","SO!")
 

Вы заметите разницу между Python 2 и Python 3. В Python 2 (...,...) интерпретируется как кортеж, поскольку print является оператором, тогда как в Python 3 это вызов функции. с несколькими аргументами.

Поэтому, чтобы ответить на поставленный вопрос, print оценивается как оператор в python 2.x, если только вы не из __future__ import print_function (представлено в python 2.6)

2

print("Hello SO!") оценивается как оператор print ("Hello SO!") , где аргументом оператора print является выражение ("Hello SO!") .

Это может иметь значение, если вы печатаете более одного значения; например print("Hello", "world") напечатает двухэлементный кортеж ("Hello", "world") вместо двух строк "Hello" и "world" .

Для совместимости с Python 3 используйте из __future__ import print_function :

 >>> print("Hello", "world")
('Привет, мир')
>>> из __future__ импортировать print_function
>>> print("Привет", "мир")
Привет, мир
 

2

Он по-прежнему оценивается как оператор, вы просто печатаете ("Привет, ТАК!") , который просто оценивается как "Привет, ТАК!" , так как это не кортеж (как упоминал delnan).

3

Зарегистрируйтесь или войдите в систему

Зарегистрируйтесь с помощью Google

Зарегистрироваться через Facebook

Зарегистрируйтесь, используя электронную почту и пароль

Опубликовать как гость

Электронная почта

Требуется, но никогда не отображается

Опубликовать как гость

Электронная почта

Требуется, но не отображается

В чем разница между print и print() в python 2.

7

спросил

Изменено 1 месяц назад

Просмотрено 80 тысяч раз

Я новичок в Python.

Я запускаю следующий код на python 2.7 и вижу другой результат, когда использую print или print(). В чем разница между этими двумя функциями? Я читал другие вопросы, например, этот вопрос, но не нашел своего ответа.

 класс Прямоугольник:
    def __init__(я, ш, ч):
        собственная ширина = ш
        собственная высота = h
    защита __str__(я):
        return "(Ширина: {0}, а высота: {1})".format(self.width, self.height)
поле = прямоугольник (100, 200)
печать ("коробка: ", коробка)
напечатать "коробка:", коробка
 

Результат:

 ('box:', <__main__.Экземпляр прямоугольника по адресу 0x0293BDC8>)
box: (ширина: 100, высота: 200)
 
  • питон
  • питон-2. 7

1

В Python 2.7 (и более ранних версиях) print — это оператор , который принимает ряд аргументов. Он печатает аргументы с пробелом между ними.

Итак, если вы наберете

, напечатайте «box:», box
 

Сначала печатается строка «box:», затем пробел, затем любое поле , которое печатается как (результат его функции __str__ ).

Если вы напечатаете

 ("box:", box)
 

Вы передали один аргумент, кортеж, состоящий из двух элементов («box:» и объект box ).

Кортежи печатаются как их представление (в основном используются для отладки), поэтому он вызывает __repr__ своих элементов, а не их __str__ (что должно давать удобное для пользователя сообщение).

Вот разница, которую вы видите: (Ширина: 100, а высота: 200)

результат вашего блока __str__ , но <__main__. Экземпляр прямоугольника по адресу 0x0293BDC8> — это его __repr__ .

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

 из __future__ import print_function
 

в верхней части исходного файла, чтобы сделать его немного более готовым к настоящему.

Это в основном дополнение к другим ответам.

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

Он использует тот факт, что (var) — это просто выражение в скобках в Python 2, которое просто рассматривается как var , поэтому print(var) и print var ведут себя точно так же в Python 2, но только работает при печати одной единственной переменной

Интересно, что при переходе на Python 3, print(var) (здесь вызов функции print) уже является правильным синтаксисом.

TL/DR: print(var) в Python 2 — это просто уловка, облегчающая миграцию на Python3 с использованием того факта, что (var) — это просто выражение — форма кортежа будет (var,)

В первом примере вы печатаете кортеж, но не вызываете функцию печати. Таким образом, следующее идентично:

 a = ("box: ", box)
распечатать
 

Другими словами, в первом примере вы создали кортеж и распечатали его. Разный вывод для разных типов данных.

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

print() ). Однако, если вас все еще интересуют различия (не связанные с вашим случаем), с помощью функции печати вы можете указать разделитель, конец и куда его выводить, как описано в документации.

2

В Python 2.7 print() работает быстрее, чем print. Вот тест, сделанный с помощью Repl.it Python Console Online:

 время импорта
start_time = время.время()
печатать "лол"
end_time = время.время()
печать (конечное_время - начальное_время)
start_time_2 = время.время()
распечатать ("лол")
end_time_2 = время.время()
печать (конец_время_2 - начало_время_2)
print((end_time_2 - start_time_2) >
(end_time - start_time)) Питон 2.7.10 [GCC 4.8.2] в Linux ржу не могу 7.08103179932э-05 ржу не могу 1.00135803223э-05 ЛОЖЬ

2

В Python 2.7: print — это не функция, это ключевое слово и действует как специальный оператор.

Перед этим нам нужно больше узнать о tuple и expr в python2.

Если мы напишем («привет»): это рассматривается как выражение, а не как кортеж, его можно рассматривать как кортеж, только если введено «,».

например:

 print("привет")
>>> привет
а=("привет")
>>> "привет"
а=("привет", "мир")
>>>('привет', "мир")
print("привет", "мир")
>>> («привет», «мир»)
 

, поэтому в python2.