Print в Python 2: как подготовить код к переходу на третью версию

Раздел: Миграция -> Версии Python

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.

Print в Python 2 - comments

En
Python 2 print (python)