Вторая альфа Python 3.16: регулярные выражения стали гибче, а UUID создаются в разы быстрее

10 ноября релиз-менеджер Python 3.16 Саванна Островски объявила в блоге Python Insider о выходе второй альфа-версии, Python 3.16.0a2. Это вторая из семи запланированных альф. Новые функции в 3.16 можно добавлять до первой беты 4 мая 2027 года, а финальный релиз намечен на 5 октября 2027 года.

Ставить альфу на рабочий сервер не нужно, разработчики прямо пишут, что она для тестов. Но если вы поддерживаете библиотеку или большой проект, сейчас удобный момент прогнать тесты и посмотреть, что сломается. Заодно видно, куда движется язык: в этой версии заметно доработали регулярные выражения, генерацию UUID и сообщения об ошибках.

Регулярные выражения: операции над множествами и свойства Unicode

Модуль re научился тому, что раньше было только в сторонней библиотеке regex. Внутри квадратных скобок теперь можно вычитать один набор символов из другого ([A--B]), искать пересечение ([A&&B]) и объединение ([A||B]), причём операндом может быть вложенный набор в своих скобках. Синтаксис взят из стандарта Unicode UTS #18. Пример из документации: [a-z--[aeiou]] находит любую строчную латинскую согласную.

Вторая новинка: экранирование \p{...} и \P{...} для поиска символов по свойству Unicode. Например, \p{Lu} означает любую заглавную букву, причём не только латинскую, но и кириллицу.

import re

# строчные согласные латиницы: весь диапазон a-z минус гласные
print(re.findall(r"[a-z--[aeiou]]+", "python"))   # ['pyth', 'n']

# заглавные буквы любого алфавита
print(re.findall(r"\p{Lu}", "Привет, World"))     # ['П', 'W']

Раньше для такого приходилось ставить пакет regex или вручную перечислять диапазоны. Если ваш код должен работать и на старых версиях Python, с переходом на новый синтаксис стоит подождать: в 3.15 и ниже такие шаблоны будут разобраны иначе или вызовут ошибку.

uuid4() и uuid7() стали быстрее в 15 и 30 раз

Юрий Селиванов переписал на C генерацию uuid4() и uuid7(), а также сам класс uuid.UUID. Чистая реализация на Python осталась как запасной вариант. По микробенчмаркам из What’s New uuid4() стал быстрее в 15 раз, uuid7() почти в 30 раз, а разбор UUID из строки и обратное преобразование в строку быстрее примерно в 6,7 раза.

Для веб-проектов это приятная мелочь: UUID часто служат первичными ключами в базе и идентификаторами запросов, так что их генерация вызывается постоянно. Одно изменение может задеть старый код: если передать в uuid.UUID через bytes или bytes_le что-то кроме объекта bytes, теперь всегда будет TypeError. Раньше в таких случаях могли вылетать AssertionError или ValueError.

Быстрее запуск и понятнее ошибки

Интерпретатор стал быстрее запускаться, а сборщик мусора делает меньше лишней работы. Ускорили создание списков, словарей, bytes и bytearray, итерацию по асинхронным генераторам (бенчмарк async_generators быстрее примерно на 30%), а ast.parse() стал быстрее на 16% и тратит на дерево на 52% меньше памяти. Парсинг дат через strptime() по частым форматам вроде %Y-%m-%d тоже ускорили.

Сообщения об ошибках подсказывают ещё больше. Если по привычке из другого языка написать switch x:, Python предложит match, вместо delete x предложит del, вместо function f(): предложит def. На && и || он подскажет and и or. А если метод вызвали с лишним позиционным аргументом, ошибка напомнит проверить, не забыт ли self в определении.

Что ещё полезно админам и веб-разработчикам

  • Модуль ssl поддерживает Encrypted Client Hello (ECH), если Python собран с OpenSSL 4.0 или новее. ECH шифрует начало TLS-соединения, включая имя сайта, к которому подключается клиент.
  • В asyncio.run() и asyncio.Runner появился параметр eager_tasks, а в start_unix_server() параметр mode, чтобы сразу задать права на файл Unix-сокета.
  • В zipfile появились ZipFile.remove() и ZipFile.repack(): теперь можно удалить файл из архива и освободить место без пересборки всего архива.
  • У ipaddress есть метод next_network(), который находит следующую подсеть нужного размера.
  • imaplib получил методы move() и login_plain() и сам кодирует русские названия почтовых папок.
  • В datetime появился формат %Nf, где N от 1 до 6: можно выводить не все шесть знаков микросекунд, а например только миллисекунды.

Что убрали и что может сломаться

В 3.16 окончательно удалили то, что объявили устаревшим в 3.14. Самое заметное для веб-проектов: из asyncio убрали систему политик цикла событий, то есть get_event_loop_policy(), set_event_loop_policy() и классы вроде WindowsSelectorEventLoopPolicy. Вместо них нужно передавать свою фабрику цикла через loop_factory в asyncio.run() или asyncio.Runner. Также удалён asyncio.iscoroutinefunction(), его заменяет inspect.iscoroutinefunction().

Из других изменений: typing.AnyStr теперь выдаёт предупреждение об устаревании и исчезнет в Python 3.21, abc.abstractproperty и похожие классы тоже начали предупреждать. Полный список есть в разделах Removed и Deprecated.

Быстро проверить, не тянет ли проект что-то из удалённого, можно поиском по коду:

grep -rnE "set_event_loop_policy|get_event_loop_policy|EventLoopPolicy|asyncio\.iscoroutinefunction" --include=*.py .

Как попробовать

Исходники и установщики для Windows и macOS лежат на странице релиза на python.org. Найденные ошибки разработчики просят присылать в трекер CPython на GitHub. Следующая альфа, 3.16.0a3, по графику PEP 826 выйдет 15 декабря 2026 года.

Итог: для продакшена 3.16 ещё рано, до финального релиза почти год. Но проверить на альфе свою библиотеку или проект на asyncio уже имеет смысл, особенно если в коде остались политики цикла событий. А новые возможности re и быстрые UUID, скорее всего, станут главными причинами перейти на 3.16, когда он выйдет.

Источники и ссылки


Комментарии загружаются…