Python 3.14 вийшов у світ: REPL, t-рядки, Free-threaded Python й інше

💡 Усі статті, обговорення, новини про Python — в одному місці. Приєднуйтесь до Python спільноти!

Привіт, з вами Артур! Python 3.14 було випущено 7 жовтня 2025 року. Є доволі цікаві зміни та фічі, які хотілось би розглянути.

Основне це:

  • Free-threaded Python — пака-пака, GIL — потоки тепер працюють паралельно, а не чекають своєї черги.
  • t-рядки — шаблонні рядки, які не обчислюються одразу.
  • REPL — підсвічування синтаксису, автодоповнення модулів в import, кастомні теми; веселий псевдонім «πthon» у venv.
  • Повідомлення про помилки — ще зрозуміліші синтаксичні та рантайм-підказки.
  • Ексепшени — можна except ValueError, TypeError без дужок (якщо без as).
  • Попередження для return/break/continue у finally.
  • Типи: відкладені (lazy) анотації (PEP 649) + нові API get_annotations() / get_type_hints().

Exceptions Without Parentheses

Раніше коли ви перехоплювали декілька ексепшенів, їх треба було огорнути у дужки, а тепер не треба :) Жити стало краще, менше візуального шуму. Але можете продовжувати робити як і було раніше — ругатись не буде.

Better Error Messages

Замість того, щоб просто вказувати, що щось пішло не так, Python тепер точно визначає першопричину і часто підказує спосіб виправлення, адресуючи типові помилки, яких найчастіше припускаються як новачки, так і досвідчені розробники. Узагальнені повідомлення типу «invalid syntax» тепер більш конкретні й описові.

Наприклад, коли ви робите друкарську помилку в ключовому слові, Python 3.14 часто може здогадатися, що ви мали на увазі, і запропонувати правильне написання:

Template Strings (T-Strings)

Мабуть, натхненні JavaScriptʼом, нові рядки-шаблони (template strings) Python (або t-рядки) — певно, найбільш помітне доповнення. Синтаксично t-рядки дуже схожі на f-рядки. На перший погляд єдина видима відмінність — це префікс, бо рядки-шаблони починаються з t або T.

Однак, на відміну від f-рядків, t-рядки обчислюються у новий об’єкт string.templatelib.Template, а не безпосередньо до звичайного str.

Основною мотивацією для введення t-рядків і нового класу Template було бажання зберегти зручність і читабельність f-рядків, одночасно з цим зробивши їх безпечнішими.

З f-рядками ви могли зробити щось подібне:

і отримати вразливість SQL-інʼєкції.

Тут поможуть t-рядки. На відміну від f-рядків, t-рядки перехоплюють значення до їх «злиття» з шаблоном, додаючи додатковий рівень безпеки. Вони дозволяють вам перевіряти введення, тож ви можете примусово застосувати типи, екранувати або відхиляти небезпечні символи.

Змінивши визначення функції get_user() так, щоб вона повертала шаблон рядка замість звичайного рядка, ви можете відкласти підстановку значень, наданих користувачем.

Тепер ви маєте написати власний процесор шаблонів або знайти його в сторонній бібліотеці.

Кольоровий REPL

Перше, що ви можете помітити — REPL став «яскравішим». Насправді іще з 3.13 почали відбуватись зміни в до цього мінімалістичному REPLʼі, але в цьому релізі стрибнули ще вище. Дві нові можливості це:

  • Підсвічування синтаксису: підсвічування в реальному часі з налаштовуваними темами.
  • Автодоповнення коду: автоматичне доповнення назв модулів у виразах import.

Тепер REPL майже як повноцінний редактор коду :D Ключові слова, рядки, коментарі, числа й оператори — кожен із них має власний колір, використовуючи ANSI escape-коди, подібні до тих, що вже надають колір підказкам і трасуванням у Python 3.13.

Також плюшки отримали деякі стандартні ліби. Наприклад:

Модуль calendar підсвічує поточний день, модуль json форматує у зручному для читання вигляді, модуль unittest дає кольоровий вигляд зафейлених assertʼів.

Якщо ж стандартні кольори вам не подобаються і хочете зробити шось кастомне, то можна зробити це через власний скрипт для старту Python.

/.pythonrc.py

try:
    from _colorize import ANSIColors, default_theme, set_theme
except ImportError:
    pass
else:
    custom_theme = default_theme.copy_with(
        syntax=default_theme.syntax.copy_with(
            number="\x1b[38;5;227m"
        )
    )
    set_theme(custom_theme)

import platform
import sys

version = platform.python_version()
sys.ps1 = f"{version}>>>"
sys.ps2 = "." * len(sys.ps1)

«\x1b[38;5;227m» — це ANSI-кольори. Шпаргалка тут talyian.github.io/ansicolors.

Конкретно тут ми замінили колір цифр та додали версію інтерпритатора Pythonʼа. Якщо кольори не подобаються можна їх вимкнути встановивши енв. змінну NO_COLOR=1 , або PYTHON_COLORS=0.

Також у Python 3.14 доповнення Tabʼом тепер розуміє контекст інструкцій import і from ... import, пропонуючи назви модулів і пакетів із вашого поточного шляху імпорту:

Warnings in try…finally Blocks

Блоки try...finally у Python призначені для гарантії, що код блока finally виконається незалежно від того, як завершується блок try. Але використання певних конструкцій керування потоком усередині finally може бути трошки проблематичним.

Якщо виконати return, break або continue з блоку finally, ви можете непомітно «перекрити» активний ексепшн або пропустити якийсь клін-ап, що веде до заплутаної поведінки. Наприклад:


У Python 3.13 і раніших версіях ця функція повністю «проковтнула» б Error і повернула рядок «qwe». І ви б ніколи не побачили виняток, що робить дебагінг складним. Подібний ефект виникає, коли ви використовуєте break або continue всередині блоку finally. Усі ці ключові слова можуть перевизначати керування потоком так, що приховується початкова причина спрацьовування блоку.

Протягом багатьох років ця особливість була відомою «пасткою» в мові. PEP 765 запропонував компроміс. Починаючи з Python 3.14, таке використання все ще «легальне» заради зворотної сумісності, але інтерпретатор тепер видає SyntaxWarning, щоби явно вказати на ризик:

Ви можете сприймати ці попередження як можливість переглянути свій дизайн. Зазвичай виправлення просте: перенесіть оператор керування потоком за межі блоку finally або переробіть логіку так, щоб блок finally виконував лише очищення, а не керування потоком.

Type Checking

Проблема, яка була вирішена у релізі 3.14 доволі цікава. Уявіть такий код:

В ранніх версіях ми отримаємо NameError, бо інтерпретатор не може розпізнати Inner. На цьому етапі клас Inner ще не визначено. Переставлення класів може допомогти, але скоріше ви просто перенесете проблему з одного місяця в інше.

В Python 3.7 з’явилась концепція postponed evaluation of annotations.

Це свого роду костиль був доволі довго — по суті це перетворення типів у просто рядки. Тепер же, замість перетворення анотацій на рядки, що могли вимагали б ручного обчислення, Python 3.14 репрезентує їх як дескриптори даних, які обчислюються лише за потреби, а потім кешуються. Такий підхід уникає і «жадібного» ексек’юшену та проблем «стрігнування».

Deferred Evaluation of Annotations

Як випливає з назви PEP 649 — «відкладене обчислення анотацій» — Python 3.14 усе ще обчислює анотації за вас, але лише коли ви явно їх запитуєте. Які переваги дає:

  • Відкладають обчислення до моменту доступу до анотацій, покращуючи перформанс старту.
  • Прибирають типові проблеми з прямими та зворотними посиланнями і циклічними імпортами.
  • Забезпечують послідовну інспекцію через нові утилітні функції у стандартній бібліотеці.

Ця зміна дає великий виграш: підказки типів стають швидшими, безпечнішими й простішими у використанні без поломки вашого наявного коду.

Parallel Subinterpreters

Для CPU-баунд задач у звʼязку з глобальним блокуванням інтерпретатора (GIL) лише один потік може виконувати байткод Python у будь-який момент, тож додаткові потоки не дають справжнього паралелізму. Традиційний воркераунд — це мультіпроцесинг. Але хоча процеси й працюють паралельно, вони мають великі витрати на запуск і обмін даними.

Python 3.14 запроваджує третю опцію, яка раніше була доступна лише через C API. Субінтерпретатори нарешті стають практичними з чистого Python — більше не потрібно спускатися до C.

Кожен субінтерпретатор має власний GIL і ізольований стан, тобто кілька інтерпретаторів можуть справді паралельно виконувати код Python на різних ядрах CPU. Вони «легші» за процеси, але все ще безпечніші за потоки, адже інтерпретатори за замовчуванням не ділять глобальні об’єкти.

Щоб зробити субінтерпретатори простими у використанні, стандартна бібліотека тепер пропонує InterpreterPoolExecutor у concurrent.futures. Він працює так само, як ThreadPoolExecutor або ProcessPoolExecutor: ви надсилаєте виклики (callables) і отримуєте результати. Під капотом кожен воркер працює у власному інтерпретаторі, тож ваші CPU-баунд задачі масштабуються на всі ядра.

Цей новий інструмент розміщується між потоками та процесами:

  • Потоки (Threads): найкраще підходять для I/O-задач, але обмежені для CPU-баунд у звичайному CPython.
  • Процеси (Processes): максимальна ізоляція та сумісність, але більші накладні витрати.
  • Інтерпретатори (Interpreters): дають справжній паралелізм з меншими витратами, ніж у процесів, але зі строгішою ізоляцією, ніж у потоків.

Субінтерпретатори в Python 3.14 дають легковаговий спосіб масштабувати «важкі для CPU» задачі на кілька ядер без витрат, притаманних процесам. Це не «срібна куля», але вони відкривають золоту середину для паралельного програмування на Python.

І доречі, гарні бенчмарки можна побачити тут.

Free-Threaded Python

У Python 3.13 було представлено експериментальну free-threaded збірку — версію CPython, що може справді паралельно виконувати кілька потоків, вимикаючи GIL. З Python 3.14 free-threaded Python отримав supported status. GIL у Python 3.14 за замовчуванням увімкнено. Щоб його вимкнути, спершу потрібно скомпілювати сорскод Python з прапорцем --disable-gil. Це створює інтерпретатор без GIL, який дозволяє кільком нативним потокам одночасно виконувати код Python.

Incremental Garbage Collector

У Python давно є автоматичне керування пам’яттю. Цей механізм спирається на підрахунок посилань. Додатково Python використовує збирання сміття для складніших випадків, як-от цикли посилань. Цикл утворюється, коли два об’єкти посилаються один на одного, утримуючи їхні лічильники посилань більше нуля, навіть коли жодна змінна більше на них не вказує.

Дотепер, коли спрацьовував детектор циклів, він намагався виконати все прибирання одразу, що могло на мить «підвісити» вашу програму, якщо накопичилося багато об’єктів. У Python 3.14 це змінилось. Замість того щоб «підмітати» все за раз, він розподіляє роботу на кілька кроків — інкрементально. Це означає коротші паузи, які ледь помітні, навіть під значним навантаженням.

Наче головне, що трапилось, розписав. Доволі великі зміни у цьому релізі. Ну а оновлюватись чи ні — тут уже самі обирайте, оскільки є і переваги, і ризики у цьому релізі.

Всім гарного дня, стабільних релізів та буду радий бачити у своїй групі, щоб слідкувати за оновленнями світу айтішки!

👍ПодобаєтьсяСподобалось19
До обраногоВ обраному5
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
У Python давно є автоматичне керування пам’яттю.

Довольно давно, наверное тогда же когда и выпустили оператор if.
Простите, просто формулировка забавная.

:D «З часів давніх богів, воєвод та царів» :D (цитата з ксени принцеса воїн) :D

Finally, π-thon!

(честно спёр из чятика)

думав вставити цю картінку тоже :D :D :D

Артуре, дякую за розгорнутий огляд!

А я ось на t-strings зробив рендерер secret_safe, який знаходить секрети в рядках та змінює їх на *****: Template Strings — нові рядки-шаблони у Python 3.14.

Энтропия растёт!

Я так підозрюю, імена на зразок Вішванатанхтан Раджапраджхалкумар воно теж вважатиме секретами?

Ні, ваше імʼя не дістає до порогу 3,8:

>>> shannon_entropy("Раджапраджхалкумар")
3.1916116417513782

Алгоритм Шеннона обрав як самий простий для proof of concept.

Підписатись на коментарі