Представьте: ваш Python-код работает на 30% быстрее благодаря JIT-компиляции, обработка запросов масштабируется на все ядра процессора без ограничений GIL, а отладка высоконагруженных систем происходит в реальном времени, без остановки продакшена. Это не футуристический сценарий “what-if” — это реальность Python 3.14, релиза, который переосмысливает саму природу разработки с высокой производительностью на Python.

Блок finaly

Самое простое, понятное и в то же время невероятно полезное изменение для многих разработчиков: в блоке finally теперь запрещено использовать return, break или continue. Давайте разберёмся на практике, что это значит для нас.

В старых версиях Python: даже если при чтении кода казалось, что вернётся 1, и программа завершится, на деле могло вернуться 2.

В Python 3.14 ситуация изменилась: код по-прежнему выполняется, но теперь вы всегда получите предупреждение, если внутри finally есть return.

Блок finaly
Блок finaly

Ранее обсуждалось предложение полностью запретить return, break и continue внутри блока finally — как это описано в PEP 765. Но полное блокирование сломало бы слишком много существующего кода, поэтому решили ограничиться предупреждением, чтобы программисты видели рискованную конструкцию и старались её не использовать.

И ещё один приятный бонус: теперь на собеседовании вас не смогут поймать на этом «трюке». Код сразу покажет предупреждение, и этот вопрос больше не будет «со звёздочкой», как любят задавать некоторые интервьюеры.

Стандартная библиотека compression и формат Zstandard

Следующее крупное нововведение — новая стандартная библиотека compression, которая предлагает набор инструментов для сжатия данных. С её помощью данные занимают меньше памяти, снижается потребление ОЗУ, а работа с ними становится более эффективной. Давайте посмотрим, в чём суть.

Компания Meta* (ранее Facebook) (*признана экстремистской и запрещена в Российской Федерации) разработала формат Zstandard — высокоэффективный алгоритм сжатия. Ранее для его использования требовалась сторонняя библиотека, но теперь Zstandard встроен в Python через модуль compression.zstd — это реализовано в PEP 784 «Adding Zstandard to the standard library».

Представьте ситуацию: у вас есть длинная строка, которая вам пока не нужна (да, такое бывает). Вы её получили, сохранили и начнёте работать с ней только через некоторое время.

Что делаем дальше:

  1. Переводим строку в байты (для демонстрации можно умножить её на 5, чтобы увеличить объём)

  2. Используем zstd из модуля compression

  3. Сжимаем данные и измеряем длину новых сжатых данных относительно исходных

Если выполнить этот процесс, можно получить процент сжатия примерно 0,33, то есть освободилось около 67% памяти. Теперь ОЗУ «дышит» свободнее и может использоваться для других задач.

Сжатие строки
Сжатие строк��

Ещё один нюанс: чем более однородные данные, тем эффективнее сжатие. Если строка содержит много повторяющихся элементов (например, умножаем на 100 раз) — процент сжатия ещё выше. На практике мы можем уменьшить объём данных примерно в 100 раз.

Сжатие строки
Сжатие строки

И, разумеется, после сжатия данные можно «расжать» ? обратно, вернув исходную строку без потерь.

Типизация

Раньше, если вы использовали какой-то тип данных (созданный самостоятельно или импортированный), но он объявлялся после использования, приходилось оборачивать его в кавычки. И это немного раздражало: когда пишешь код, хочется, чтобы всё шло «плавно» и «спокойно», без лишних мелочей вроде «надо ли кавычку поставить, или не надо». В Python 3.13 вызов такого кода приводил к ошибке: «тип не определён». А если обернуть его в кавычки — работало.

Объявление после использования без кавычек в Python 3.13
Объявление после использования без кавычек в Python 3.13

Вы можете спросить: зачем сначала использовать тип, а потом его объявлять? Причина проста: иногда порядок нельзя изменить из-за циклических импортов или других ограничений — иначе код просто сломается.

Объявление после использования с кавычками в Python 3.13
Объявление после использования с кавычками в Python 3.13

С выходом Python 3.14 эта проблема решена: можно использовать типы данных без кавычек, даже если их объявление идёт позже. Небольшое улучшение, но очень удобное: теперь код чище, и кавычек в нём стало меньше.

Объявление после использования без кавычек в Python 3.14
Объявление после использования без кавычек в Python 3.14

Шаблонные строки (t-строки)

Следующая фича: появилась новая строковая форма — t-строки (от template). Мы все привыкли к f-строкам. Но теперь: t-строка — это не просто строка, это определённый тип Template, с которым можно работать и в котором можно проходиться циклом по всем параметрам, подставляемым в шаблон, и что-то с ними делать. Пока не совсем ясно, где это применить. Но, например — противодействие SQL инъекциям: если мы видим, что есть запрос с «инфекцией», мы можем сделать raise или очистить запрос от зловредных конструкций.

Шаблонные строки (t-строки)
Шаблонные строки (t-строки)

Несколько исключений без скобок

Если вы используете несколько исключений в блоке tryexcept, и раньше оборачивали их в скобки, — теперь этого делать не надо. Это мелкая, но удобная вещь.

Несколько исключений без скобок в Python 3.13
Несколько исключений без скобок в Python 3.13
Несколько исключений со скобками в Python 3.13
Несколько исключений со скобками в Python 3.13
Несколько исключений без скобок в Python 3.14
Несколько исключений без с��обок в Python 3.14

Интерфейс отладки без накладных расходов

Следующая фича в Python 3.14 — реально крутая. Раньше мы пользовались дебаггерами вроде PyCharm или VS Code, но они не были идеально приспособлены для продакшена. Сейчас же можно всё делать максимально удобно. Речь идёт о новом интерфейсе отладки с zero-overhead, то есть без каких-либо дополнительных нагрузок на программу.

Представим ситуацию: у вас есть приложение с несколькими синхронными функциями, и главная функция запускает остальные задачи по очереди. Одна задача может выполняться, например, 1000 секунд, а другие — меньше. Что хочется узнать? Работает ли сейчас программа, занята ли она, зависла ли или что-то сломалось? Вопросы такие возникают потому, что иногда забываешь добавить логи или происходят неожиданные события, влияющие на работу. И хочется подключиться к коду, чтобы понять, что происходит, не прерывая выполнение и не теряя прогресс.

Что делает Python 3.14: мы можем подключиться к работающему коду, выполнить в нём дополнительный скрипт и посмотреть текущее состояние: какая функция выполняется, какие значения имеют переменные или приостановить выполнение. Для этого потребуется отдельный .py-файл, который внедряется в основной процесс.

Принцип работы простой:

  1. Пишем код в виде строки, который хотим внедрить в процесс

  2. Сохраняем его временно в файл

  3. Через ID процесса подключаемся к запущенному Python и говорим: «выполни этот файл прямо в процессе»

Отладка с помощью .py файла
Отладка с помощью .py файла

JIT-компиляция (экспериментально)

Итак, друзья, прежде чем перейти к теме параллельности, разберём ещё одну фичу — экспериментальный JIT-компилятор (just-in-time compilation). Маленькая ремарка: почему Python иногда кажется медленным?

JIT работает так: если есть участок кода, который выполняется часто (например, цикл), интерпретатор может распознать его, скомпилировать в машинный код и выполнять напрямую. В результате интерпретация Python-кода больше не нужна, а выполнение происходит напрямую на процессоре, что потенциально ускоряет программу в несколько раз.

На данный момент JIT в Python 3.14 экспериментальный. Он не включён в стандартную сборку и не рекомендуется для продакшена. Чтобы попробовать его, придётся собрать Python из репозитория CPython.

На практике JIT может как замедлять выполнение на ~10%, так и ускорять его примерно на 30%. То есть особого прироста производительности пока ждать не стоит, но важно, что движение в сторону ускорения кода уже есть.

Параллельность в Python

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

Теперь есть возможность подключаться к процессу иначе — с помощью встроенного модуля pdb. С его помощью можно остановить выполнение программы, исследовать её состояние и управлять кодом. После выхода из pdb выполнение продолжится с того места, где вы остановились.

Отладка в консоли с помощью модуля pdb
Отладка в консоли с помощью модуля pdb

Это позволяет подключаться к программе снова и снова, проверять состояние переменных, функции и поток выполнения. Звучит прикольно, правда? Особенно полезно, если вы работаете с мультипроцессингом, ML-моделями или любой тяжёлой обработкой данных, которая может занимать часы и дни. Можно буквально «снимать снепшоты» текущего состояния программы: подключился, посмотрел, отключился — и всё продолжает работать

Free-threaded Python и многопоточность

А вот теперь — самая классная часть — следующие две фичи, которые, возможно, перевернут то, как вы работаете с Python и как в принципе Python воспринимают. Раньше это был «какой-то медленный язык для скриптов», а сейчас «немного более быстрый язык для скриптов».

Первая фича: Free-threaded Python, вторая — новый тип интерпретатора. Обе достаточно сложны для восприятия, но попробуем рассказать понятным языком.

Free-threaded Python

В Python есть поддержка многопоточности, но на практике мы её используем редко, если речь идёт о задачах с высокой нагрузкой на CPU: обработка видео, фото, больших датасетов, матриц, ML и т.д. В таких случаях чаще применяют многопроцессинг.

Если же мы говорим о бэкенде, написании API, работе с базами данных, брокерами сообщений, кэшем или внешними API — здесь больше подходит асинхронность. Потоки там почти не нужны, разве что библиотека не имеет асинхронной версии. Например, для ClickHouse долго не было асинхронного клиента, и тогда приходилось использовать многопоточность.

Главная проблема с потоками — GIL (Global Interpreter Lock). Из-за него несколько потоков не могут одновременно выполнять Python-код. В итоге CPU-задачи нельзя распараллеливать. Да, многопоточность могла обрабатывать запросы к API или кэшу, но работать с потоками сложно: race condition, трудности с отладкой. Как понять, какой поток сейчас активен? Как часто происходит переключение между потоками? В асинхронном коде всё более предсказуемо и последовательнее.

Теперь в Python 3.14 появляется Free-threaded Python. Это «бесплатно потоковый» режим, где GIL больше не ограничивает потоки. Все потоки могут реально выполняться параллельно, и мы можем обрабатывать CPU-задачи одновременно. В отличие от процессов, которые тяжеловесны, поток — лёгкий и удобный инструмент. «Запустить новый поток? Проще простого», и на практике мы уже видели, как это работает.

Сравнение однопоточности, многопоточности и мультипроцессинга
Сравнение однопоточности, многопоточности и мультипроцессинга
Многопоточность с отключённым GIL
Многопоточность с отключённым GIL

И это ещё не всё — дальше ждёт ещё одно нововведение, которое делает параллельность в Python ещё интереснее.

Новый тип интерпретатора

Это еще одно классное и реально революционное обновление в Python 3.14. Теперь можно запускать несколько интерпретаторов Python одновременно. Звучит дико, ведь раньше у нас всегда был один интерпретатор на программу, даже если приложение многопоточное или асинхронное.

Что это даёт и для каких задач полезно? С появлением модуля concurrent.interpreters (PEP 734) мы получаем настоящий параллелизм на нескольких ядрах и более удобную модель конкурентности.

Вы, наверное, думаете: «А зачем это нужно? Почему не использовать асинхронность, многопоточность, мультипроцессинг или Free-threaded Python?» Основная причина — избежать проблем с глобальным состоянием. То есть избавиться от race-condition, когда несколько потоков имеют доступ к одним и тем же данным и могут их перезаписывать, вызывая ошибки и аномалии. С потоками с этим сложно работать.

При запуске нескольких интерпретаторов память не общая. Мы остаёмся в одном процессе, но каждый интерпретатор имеет свои переменные и данные. Если нужно передать объект другому интерпретатору — он копируется, ссылка на объект не передаётся.

Идея появления нескольких интерпретаторов частично связана с концепцией sandbox. Если требуется выполнить код в изолированной среде, вместо создания нового процесса (что ресурсоёмко), можно запустить отдельный интерпретатор и попросить его выполнить код. Звучит почти невероятно, но работает.

Итак, теперь в Python есть: асинхронность, «старая» многопоточность, Free-threaded Python, мультипроцессинг и возможность запускать несколько интерпретаторов параллельно. Каждое решение полезно в своём контексте.

Новый тип интерпретатора
Новый тип интерпретатора

Заключение

Выше мы перечислили основные нововведения. Надеюсь, вы найдёте применение всем этим классным возможностям Python 3.14.

Код из статьи

Комментарии (0)