Print в Python 2: как подготовить код к переходу на третью версию
Print в Python 2: подготовка к миграции на Python 3
В Python 2 команда print является оператором, а не функцией, что вызывает серьёзные отличия в синтаксисе и поведении при переносе кода на Python 3. При миграции проектов необходимо учитывать эти различия и выбирать подходящий способ адаптации.
Как сделать print-оператор совместимым с Python 3 без изменения основного кода?
Наиболее эффективное решение - использование модуля __future__. Импорт from __future__ import print_function превращает print в функцию, полностью аналогичную версии Python 3. Это позволяет писать код, который будет работать в обоих интерпретаторах (Python 2.7+).
# Python 2 (оператор)
print "Hello, world!"
# Python 2 с __future__ (становится функцией)
from __future__ import print_function
print("Hello, world!")Python 2 import (импорт в python 2)
Проблема: без импорта from __future__ import print_function вызов с круглыми скобками в Python 2 трактуется как печать кортежа, если после скобок нет запятой. Например, print("a", "b") выведет ('a', 'b'), а не a b.
Решение: всегда добавлять указанный импорт в начале файлов при миграции.
Цель: обеспечение обратной совместимости с Python 2 при постепенном переходе на Python 3.
Как вывести несколько аргументов без пробела или с другим разделителем?
Вариант - использовать параметры sep и end, доступные только в функции print (Python 3 или __future__). Для Python 2 без будущего импорта приходится прибегать к sys.stdout.write().
from __future__ import print_function
print("a", "b", "c", sep="|", end=" FIN\n") # a|b|c FINпрограммы на python 2 (программы на python 2)
Ошибка: попытка использовать sep в Python 2 без импорта вызовет SyntaxError.
Как направить вывод не в стандартный поток, а в файл?
В Python 3 функция print поддерживает параметр file. В Python 2 без будущего импорта это можно сделать через sys.stdout или переопределением >>.
# Python 2 (оператор) - синтаксис с >>
with open('out.txt', 'w') as f:
print >> f, "Write to file"
# Python 2 с __future__
from __future__ import print_function
with open('out.txt', 'w') as f:
print("Write to file", file=f)
Python 3 программы (программы на python 3)
Проблема: оператор >> не работает с функцией print (после импорта), и наоборот. При миграции весь код с >> нужно заменять на file=.
Как подавить перевод строки в конце вывода?
В Python 3 - параметр end=''. В Python 2 без будущего импорта ставится запятая в конце оператора.
# Python 2 (оператор)
print "without newline",
print "continues on same line"
# Python 2 с __future__
from __future__ import print_function
print("without newline", end='')
print("continues on same line")Python 2 print (print в python 2)
Нюанс: запятая в Python 2 добавляет пробел перед следующим выводом, а end='' убирает только перевод строки. При миграции это может слегка изменить форматирование.
Как полностью избежать синтаксических различий между версиями?
Вместо использования оператора print в Python 2 можно отказаться от него в пользу sys.stdout.write(). Этот способ работает одинаково в обеих версиях, но требует явного добавления пробелов и переходов строк.
import sys
sys.stdout.write("Hello ")
sys.stdout.write("world!\n")Install python 64 bit (установка python 64-bit)
Недостаток: код становится более многословным и теряет преимущества автоматического форматирования, доступные в функции print.
Цель: получить максимально переносимый код, если библиотека __future__ нежелательна.
Как использовать print-функцию в Python 2, если импорт __future__ недоступен (например, в нестандартной среде)?
Можно определить собственную функцию, эмулирующую поведение print() из Python 3.
import sys
def print3(*args, sep=' ', end='\n', file=sys.stdout):
output = sep.join(str(arg) for arg in args)
file.write(output + end)
print3("a", "b", sep="-") # a-b
Проблема: такая реализация может не поддерживать все особенности (например, вызов с пустыми скобками), и её нужно включать в каждый модуль.
Расширенные примеры использования print при миграции
Пример 1. Печать кортежа vs печать нескольких значений
# Python 2 (оператор) – печатает кортеж, если использовать скобки без запятой
print ("Hello", "world") # вывод: ('Hello', 'world')
# Python 2 с __future__ – печатает как функция
from __future__ import print_function
print("Hello", "world") # вывод: Hello world
('Hello', 'world')
Hello world
Пояснение:
в Python 2 выражениеprint ("a", "b") воспринимается как оператор print, которому передан кортеж ('a', 'b'). После импорта __future__ скобки становятся вызовом функции, и аргументы передаются через запятую.
Пример 2. Использование параметров sep, end и file одновременно
from __future__ import print_function
import sys
with open('log.txt', 'a') as log:
print('Ошибка', 'код 404', sep=': ', end=' |\n', file=log)
print('Время', '12:30', file=log)
(содержимое файла log.txt): Ошибка: код 404 | Время 12:30
Пояснение:
параметрsep заменяет стандартный пробел, end определяет завершающую строку, file указывает файл. В Python 2 без __future__ такой синтаксис не поддерживается.
Пример 3. Перенаправление потока с помощью оператора >> в Python 2
import sys
# Python 2 (оператор) – перенаправление в stderr
print >> sys.stderr, "Критическая ошибка: деление на ноль"
Критическая ошибка: деление на ноль (в потоке stderr)
Пояснение:
символ>> направляет вывод в указанный файлоподобный объект. Этот синтаксис отсутствует в Python 3, поэтому при миграции его заменяют на print(..., file=sys.stderr).
Пример 4. Подавление перевода строки и пробелов через sys.stdout.write
import sys
# Альтернатива print без перевода строки
numbers = [1, 2, 3]
for n in numbers:
sys.stdout.write(str(n) + '-')
# Вывод: 1-2-3-
# В конце нет перевода строки
sys.stdout.write('\n') # добавляем принудительно
1-2-3-
Пояснение:
sys.stdout.write не добавляет ни пробелов, ни перевода строки, что даёт полный контроль, но требует явного форматирования. Этот метод одинаково работает в Python 2 и 3.
Пример 5. Многострочный вывод с разделителями и отсутствием пробела
from __future__ import print_function
# Печать таблицы с разделением табуляцией и окончанием без новой строки
for i in range(3):
for j in range(3):
print(i * j, end='\t' if j < 2 else '\n')
0 0 0 0 1 2 0 2 4
Пояснение:
используя параметрend с условным выражением, можно формировать строки таблицы. В Python 2 (без __future__) пришлось бы накапливать строку в переменной.
Пример 6. Работа с Unicode при выводе
# Python 2 – оператор print может выводить Unicode, но с предосторожностями
print u"русский текст" # работает, если кодировка терминала позволяет
# Python 2 с __future__ и Python 3 – автоматическая поддержка
from __future__ import print_function
print("русский текст")
русский текст
Пояснение:
в Python 3 все строки являются Unicode. При миграции желательно сразу перейти на использованиеfrom __future__ import unicode_literals (если не применяется __future__ для print) или использовать функцию print с импортированным print_function.