
Python 2 официально перестал поддерживаться с января 2020 года, однако во многих проектах он до сих пор встречается. Понимание ключевых различий помогает разработчикам корректно переносить код и избегать ошибок совместимости.
Работа со строками: в Python 2 строки по умолчанию хранятся в виде байтов, а тип unicode нужно указывать явно. В Python 3 наоборот – строки являются Unicode, а для байтов используется отдельный тип bytes. Это избавляет от путаницы при работе с текстами на разных языках и кодировками.
Деление чисел: Python 2 выполняет целочисленное деление при использовании оператора /, если оба аргумента – целые числа. В Python 3 этот же оператор всегда возвращает число с плавающей точкой, а для целочисленного деления необходимо использовать //. Такое изменение уменьшает количество скрытых логических ошибок.
Сравнение работы с текстовыми строками и байтами
В Python 2 строки по умолчанию представляют собой последовательность байтов (тип str), а Unicode-строки требуют явного указания через префикс u (u"текст"). В Python 3 текстовые строки (str) всегда хранятся в формате Unicode, а отдельный тип bytes используется для бинарных данных.
- Конкатенация: В Python 2
str + unicodeавтоматически пытается перекодироватьstrв Unicode, что может вызватьUnicodeDecodeError. В Python 3str + bytesзапрещена, требуется явное преобразование через.encode()или.decode(). - Индексация: В Python 2 байтовая строка возвращает символ в виде строки длиной 1, Unicode – тоже строку длиной 1. В Python 3
str[i]возвращает символ Unicode, аbytes[i]возвращает целое число от 0 до 255. - Методы: Методы
.encode()и.decode()в Python 3 строго разделены:str.encode()→bytes,bytes.decode()→str. В Python 2 метод.decode()применим кstr,.encode()– кunicode. - Форматирование: В Python 2 форматирование байтовых строк допускает вставку Unicode с возможной автоматической конверсией. В Python 3 необходимо привести данные к одному типу, иначе возникает
TypeError.
Рекомендации при переходе на Python 3:
- Использовать
strдля текста,bytesдля бинарных данных. Никогда не смешивать их без явного преобразования. - При чтении файлов в текстовом режиме применять
encoding="utf-8"для корректной работы с Unicode. - При работе с сетевыми протоколами или бинарными форматами использовать только
bytesи методы.encode()/.decode()для конвертации. - Избегать автоматического смешивания типов; проверять тип данных перед операциями с конкатенацией или форматированием.
Изменения в правилах деления чисел
В Python 2 операция деления двух целых чисел выполняет целочисленное деление, отбрасывая дробную часть. Например, выражение 5 / 2 возвращает 2. Чтобы получить результат с плавающей точкой, нужно использовать хотя бы один операнд типа float, например 5 / 2.0, или импортировать поведение Python 3 через from __future__ import division.
В Python 3 операция / всегда возвращает число с плавающей точкой, независимо от типов операндов. Например, 5 / 2 возвращает 2.5. Для целочисленного деления введён оператор //, который работает аналогично старому поведению Python 2: 5 // 2 даст 2.
При работе с отрицательными числами важно учитывать, что // в Python 3 округляет вниз к ближайшему меньшему целому, а не просто отбрасывает дробную часть. Например, -5 // 2 вернёт -3, тогда как в Python 2 -5 / 2 возвращало -2 при целочисленном делении.
Рекомендации при переносе кода с Python 2 на Python 3: заменять все выражения / для целых чисел на //, если нужен целочисленный результат, и проверять корректность округления для отрицательных значений. Использование / для получения дробного результата гарантирует одинаковое поведение для любых чисел.
Поддержка аннотаций типов и подсказок

Python 3 ввел синтаксис аннотаций типов, позволяющий явно указывать типы аргументов и возвращаемых значений функций. Например, запись def add(a: int, b: int) -> int: указывает, что функция принимает два целых числа и возвращает целое число. В Python 2 аналогичная функциональность отсутствует, любые попытки использовать подобный синтаксис вызовут синтаксическую ошибку.
Аннотации типов в Python 3 не выполняют проверку во время выполнения, их основная задача – поддержка статического анализа и автодополнения в IDE. Для проверки типов можно использовать модуль typing и сторонние инструменты вроде mypy или pyright. Python 2 не поддерживает модуль typing в стандартной библиотеке, что ограничивает интеграцию статической проверки.
В Python 3 доступны универсальные типы: List[int], Dict[str, Any], Optional[str], которые повышают читаемость кода и позволяют явно фиксировать структуру данных. В Python 2 приходилось полагаться на комментарии типа # type: List[int], что снижало эффективность автоматизированного анализа.
Рекомендуется использовать аннотации типов для всех публичных функций и методов, особенно в больших проектах и при работе с внешними библиотеками. Это упрощает документирование, снижает количество ошибок типов и повышает совместимость с современными инструментами разработки. Для совместимости с Python 2 можно применять типовые комментарии, но полноценная поддержка современных подсказок возможна только в Python 3.10+ благодаря синтаксису улучшенных аннотаций (list[str], tuple[int, int]).
Отличия в обработке ошибок и исключений

В Python 2 синтаксис обработки исключений допускает две формы: except Exception, e: и except (TypeError, ValueError), e:. В Python 3 такая запись устарела и заменена на except Exception as e:, что исключает двусмысленность и повышает читаемость кода.
Python 2 допускает перехват всех исключений с помощью except:, включая системные ошибки, что может скрыть критические сбои. Python 3 сохраняет возможность except:, но рекомендует явно указывать тип исключения, предотвращая непреднамеренное подавление SystemExit, KeyboardInterrupt и GeneratorExit.
Класс StandardError, существовавший в Python 2 как базовый для большинства встроенных исключений, в Python 3 удален. Все стандартные исключения теперь наследуются непосредственно от Exception, что упрощает обработку и делает иерархию исключений более прозрачной.
Python 3 вводит возможность использовать raise from для явного указания цепочки исключений. Это позволяет сохранять оригинальное исключение при генерации нового и обеспечивает более информативные трассировки стека:
try: ... except KeyError as e: raise ValueError("Ошибка данных") from e
Функция finally в Python 3 гарантирует корректное завершение блоков очистки даже при перехвате исключений, аналогично Python 2, но при этом обработка исключений стала более последовательной при использовании вложенных конструкций try-except-finally.
Рекомендация: при переносе кода с Python 2 на Python 3 необходимо заменить устаревшие синтаксисы except Exception, e на except Exception as e, проверить отсутствие скрытых системных исключений и использовать raise from для сохранения контекста ошибок.
Изменения в стандартной библиотеке
В Python 3 многие модули стандартной библиотеки были переименованы или перемещены для улучшения структуры. Например, модуль ConfigParser переименован в configparser, Queue стал queue, SocketServer – socketserver. Эти изменения требуют обновления импортов при миграции кода с Python 2.
Функции работы со строками и байтами теперь разделены: модуль io предоставляет TextIOWrapper для текстовых потоков и BytesIO для байтовых. Это устраняет неоднозначности Python 2 при работе с текстом и бинарными данными.
Модуль urllib разделён на urllib.request, urllib.parse и urllib.error. Старые импорты urllib2 и urlparse больше не поддерживаются, что требует явного разделения функций загрузки, анализа и обработки ошибок URL.
Модуль collections получил новые типы данных: ChainMap для объединения словарей, Counter для подсчета элементов и OrderedDict, который теперь сохраняет порядок вставки по умолчанию. Использование этих структур упрощает код и повышает читаемость.
Модуль itertools и функции встроенного типа map, filter, zip возвращают итераторы вместо списков, как в Python 2. Для совместимости с кодом, ожидающим списки, необходимо применять явное приведение через list().
Модуль subprocess улучшен: появились параметры encoding и text=True для прямой работы со строками, исключая необходимость кодирования и декодирования вручную, что снижает вероятность ошибок при работе с внешними процессами.
Рекомендуется проверять совместимость используемых сторонних библиотек: многие из них обновлены для Python 3 и используют новые имена модулей и функции, несовместимые с Python 2.
Совместимость кода и способы миграции

Python 2 и Python 3 несовместимы на уровне синтаксиса и стандартной библиотеки. Основные источники проблем: различия в функции print (инструкция vs функция), типах строк (str и bytes), делении целых чисел, методах словарей и поддержке Unicode.
Для оценки совместимости кода используется инструмент 2to3, который анализирует скрипты Python 2 и предлагает автоматические преобразования. Он корректирует синтаксис функций, заменяет методы строк и словарей, обновляет исключения и генераторы. После применения 2to3 рекомендуется ручная проверка участков с byte и unicode операциями.
Другой подход – использование библиотеки six, предоставляющей совместимый API для Python 2 и 3. Она включает обёртки для строк, итераторов, разделения модулей (urllib, queue) и функций input, что минимизирует изменения в коде.
Для постепенной миграции следует применять стратегию dual-source: поддерживать один код для обеих версий с помощью условных импортов и проверок версии через sys.version_info. Такой подход позволяет запускать тесты в обеих средах и выявлять несовместимости без полной конверсии.
При миграции крупных проектов рекомендуется разбивать процесс на этапы: подготовка зависимостей, обновление тестов, автоматическая конвертация, ручная корректировка критических модулей и окончательное удаление Python 2 совместимости. Использование CI/CD для проверки кода на обеих версиях ускоряет выявление ошибок.
Особое внимание следует уделить сторонним библиотекам: необходимо убедиться в их поддержке Python 3 или заменить на аналоги с совместимым API. В документации большинства популярных пакетов указаны минимальные поддерживаемые версии и рекомендации по миграции.
Вопрос-ответ:
Какие основные различия между Python 2 и Python 3 в работе со строками и текстом?
Главное различие заключается в том, как версии обрабатывают строки. В Python 2 строки по умолчанию являются байтовыми, а Unicode-строки требуют отдельного обозначения с помощью префикса u. В Python 3 все строки представляют собой Unicode по умолчанию, что упрощает работу с текстом на разных языках. Это также влияет на функции ввода/вывода, где Python 3 требует явного указания кодировки при работе с файлами, чтобы избежать ошибок.
Почему синтаксис функции print отличается между Python 2 и Python 3?
В Python 2 print является оператором и используется без скобок: print "Hello". В Python 3 print стал функцией, поэтому требуется скобки: print("Hello"). Это изменение было сделано для унификации синтаксиса и возможности более гибко управлять выводом, например, указывать аргументы sep и end. При переносе кода с Python 2 на Python 3 нужно обязательно исправить все вызовы print.
Как изменилось деление чисел между Python 2 и Python 3?
В Python 2 деление целых чисел по умолчанию возвращает целую часть результата: 5 / 2 = 2. Чтобы получить дробное число, использовалось деление с плавающей точкой: 5 / 2.0 или from __future__ import division. В Python 3 деление всегда возвращает число с плавающей точкой: 5 / 2 = 2.5. Целочисленное деление теперь выполняется через оператор //. Это изменение предотвращает неожиданные ошибки при математических вычислениях.
Какие изменения произошли в стандартных библиотеках между Python 2 и Python 3?
Многие модули были переименованы или перемещены. Например, модуль ConfigParser в Python 2 стал configparser в Python 3, а urllib был разделён на несколько подмодулей: urllib.request, urllib.parse и urllib.error. Эти изменения требуют адаптации кода при миграции на Python 3. Также некоторые устаревшие функции и методы были удалены или заменены на новые аналоги, что делает код более последовательным и безопасным.
