- PVSM.RU - https://www.pvsm.ru -
Появление долгожданных фич из нового REPL в PDB
Большое количество фиксов для shutil, так что можно наконец‑то перестать молиться при его использовании
Несколько небольших улучшений многопоточности
Новый синтаксис аннотаций позволяет использовать списки и лямбда‑функции.
Python 3.13 все еще не стал значительно быстрее. Увы.
Python 3.13 — отличный релиз, полный различных фич и улучшений, но уже есть тонна статей, которые подробно разбирают release notes [1]. Если вам нужна хорошая выжимка — у RealPython есть хорошая статья [2], но я не вижу смысла проходиться по ним еще раз в этой статье.
Так что мы не будем говорить про новый REPL, no‑GIL сборку, экспериментальный JIT‑компилятор, устаревшие штуки, новые плюшки системы типов или улучшенные сообщения об ошибках (как всегда, мое любимое).
Вместо этого я прочитал коротенькую книжку, которую они называют ченджлогом и мы посмотрим на то, о чем многие не говорили, но заинтересовало лично меня.
Несмотря на спартанскую эргономику, я очень люблю pdb и даже написал неплохое введение в него [3].
Но если вы когда‑либо пробовали сделать так:
try:
1 / 0
except ZeroDivisionError as e:
breakpoint()
Вы прекрасно знаете, что произойдет при попытке чтения e:
-> breakpoint()
(Pdb) e
*** NameError: name 'e' is not defined
Это выбешивает, в особенности потому, что с этим обычно сталкиваешься и так в не самом лучшем расположении духа.
И это наконец‑то исправили [4].
Слава Апофису, Кетцалькоатлю и Йормунганду!
Но это не все. Сам pdb также получил некие улучшения:
Наконец, многострочное редактирование [5]!
Автозаполнение кода [6], как в новом REPL.
break допускает использование dotted path [7], позволяя с легкостью динамически добавлять брейкпоинты в библиотеки.
Поддержка pdb в zipapps [8]. Почему бы и нет.
Исправили проглатывание аргументов в pdb CLI [9]. Это должно понравиться команде VSCode.
pdbrc наконец‑то не сломан [10]. Никогда не использовали? Вот и я нет. Потому что он не работал.
Режим post‑mortem работает даже для SyntaxError [11]. Это то, что нужно при работе с exec().
Все это само по себе уже хорошая причина использовать 3.13.
Казалось бы, 30-летний язык не должен иметь проблем при работе с путями и файлами, но, оказывается, всегда есть куда расти.
Модуль shutil [12], предоставляющий высокоуровневые операции с ФС, такие как рекурсивное удаление или копирование претерпел следующие изменения: много [13]—много [14] багов [15] было [16] исправлено [17] (в особенности относящиеся к обработке ошибок при рекурсии), а также добавлены некоторые [18] опции [19] (например, теперь есть возможность выбрать, как обрабатывать симлинки).
Я всегда опасался использовать shutil из‑за таких «особенностей». Рекурсивное погружение ломалось тем или иным образом. Благодаря этим фиксам я смогу снова попробовать использовать ее, поскольку она действительно удобна, когда работает.
Аналогично и для zipfile.Path [20] — pathlib‑совместимой обертки для обхода zip‑файлов, о существовании которой вы скорее всего не знали с момента ее появления в версии 3.8. И не знали вы о ней по очень простой причине — в ней не было ничего хорошего. Но версия 3.13 подарила нам много QoL‑патчей для нее, значительно улучшая обработку директорий, которая раньше требовало очень много телодвижений. Так что теперь ее можно будет использовать чаще.
И, наконец, сама pathlib [21] получила [22] много [23] небольших [24] оптимизаций [25], касающихся [25] производительности [26], теперь многие операции под капотом используют строки вместо объектов Path. Сериализация также должна стать быстрее. Мне нравится pathlib, но возможность боттлнека — известная проблема [27], так что это отличные новости. Сам я производительность на практике не замерял, так что пока воздержусь от комментариев.
Но дело не только в производительности - также было несколько приятных изменений в API. К примеру, Path.glob() и rglob() теперь принимают в качестве паттернов path-like объекты, Path.glob() теперь возвращает и файлы, и директории, если в конец паттерна добавить **, а также был добавлен метод Path.from_uri().
asyncio.as_completed() теперь возвращает [28] объект, который одновременно и асинхронный, и обычный итератор. Да, не что‑то масштабное, но уже неплохо.
asyncio.TaskGroup — отличная вещь, если еще не используете — настоятельно рекомендую. И теперь при вызове create_task() для неактивной группы корутина будет закрыта [29], предотвращая RuntimeWarning.
queue.Queue теперь может быть явно закрыта [30] вызовом shutdown(), помогая сообщить остальной системе, что пришло время перестать передавать ей данные.
Максимальное количество воркеров в пуле было увеличено выше 62 [31], просто на случай, если вы — тот самый человек из треда на Reddit [32].
Помните, что аннотации изначально не были ограничены только типами? Это был эксперимент, чтобы проверить, для чего их будут использовать люди и потому они принимают произвольные выражения Python.
Но, похоже, недостаточно произвольные, поскольку была добавлена возможность использования списков [33] и лямбда‑функций [34].
Тикет с баг‑репортом достаточно забавный:
The following code causes a
SystemErrorduring compilation.
class name_2[*name_5, name_3: int]:
(name_3 := name_4)
class name_4[name_5: name_5]((name_4 for name_5 in name_0 if name_3), name_2 if name_3 else name_0):
pass
Да что ты говоришь, Фрэнк, да что ты говоришь…
Что ж, посмотрим, какие еще способы поиздеваться над этим функционалом придумают разработчики.
Улучшения производительности не такие высокие [35], как ожидалось в этом релизе — как и в 3.12 мы получили лишь небольшое улучшение в традиционных бенчмарках для асинхронных операций (надеюсь, это не навредит моему оптимизму относительно pathlilb). Ускорение Python гораздо, гораздо сложнее, чем Guido предполагал. Это можно было понять из прошлых неудавшихся попыток, так что не особо удивительно.
Как я упоминал [36] в прошлом посте, инкрементальные изменения GC и правда были отменены [37], поскольку не дали ожидаемых результатов.
Более того, несмотря на большое количество улучшений import в ченджлоге, мои замеры не показали значительной разницы во времени запуска Python на моей машине.
Ну и поверх всего этого неизбежные поломки:
Если вы внимательно прочитаете изменения Path.glob() выше, вы можете заметить, что возвращаемое значение может значительно меняться и я предполагаю, что это сломает чей‑то код.
Ну и несколько других деталей, которые могут не понравиться некоторым:
Поддержка использования pathlib. Объекты path больше не могут [38] использоваться для управления контекстом. Не то чтобы это было полезно. И вообще это путало. Так что, наверное, хорошее изменение, но вы знаете [39].
Запуск новых тредов и процессов с помощью os.fork() во время выключения интерпретатора (например, из хэндлеров atexit) больше не поддерживается [40].
Позиционные аргументы maxsplit, count и flags для re.split(), re.sub() и re.subn() помечены как устаревшие [41] в пользу использования ключевых слов. Пока не убрано, просто предупреждение. Мне кажется несколько излишним.
Аналогично [42] для всех аргументов sqlite3.connect(), кроме первого.
Устаревание [43] незадокументированных функций glob.glob0() и glob.glob1(). Я терпеть их не мог, так как они путали моих студентов, так что я рад этому изменению, но все же.
Файлы .pth с названиями, начинающимися с точки или имеющие атрибут hidden теперь игнорируются [44] по причинам безопасности.
Хэдеры C API были почищены [45], так что ждем драконов с той стороны.
Разработка языка это всегда тонкий баланс между чистотой кода, современными фичами и отсутствием технического долга с одной стороны и поддержанием достаточной стабильности для сохранения продуктивности сообщества с другой.
Всегда найдутся как люди, которые будут говорить, что язык затрял в прошлом, так и те, кто будут спрашивать, почему опять все сломали. Здесь не победить. Разработка языка — работа неблагодарная.
Давайте закончим на позитивной ноте. У меня нет какой-либо категории для этих изменений:
python -m venv добавляет файл .gitignore [46], который автоматически игнорирует виртуальное окружение.
json.dumps() с indent теперь будет использовать C-энкодер JSON [47], что сделает его значительно быстрее. Ну и ошибки парсинга [48] из-за завершающей запятой теперь гораздо понятнее.
Теперь можно добавлять приватные варианты [49] в enum.
atexit() лучше работает с multiprocessing [50]. Скорее всего связано с упомянутым ранее устареванием :)
Dataclass теперь вызывает exec() один раз на 1 dataclass [51] вместо вызова для каждого добавляемого метода. Это может сделать процесс их создания до 20% быстрее.
Была добавлена объединенная операция сложения-умножения math.fma(x, y, z). На случай, если вам необходимо работать с полиномами прямо здесь, прямо сейчас.
time.sleep() теперь создает auditing event [52]. Кто-то получит письмо на эту тему и я не могу дождаться. Нет, серьезно, вы же не хотите получить sleep(1e9) в критических проектах.
Такие функции re как re.findall(), re.split(), re.search() и re.sub(), выполняющие короткие повторяющиеся сравнения теперь могут быть прерваны пользователем. Меньше причин, по которым Ctrl + C может не срабатывать.
Параметр количества в str.replace() теперь может быть ключевым словом [53].
Что удивило меня больше всего при прочтении ченджлога версий 3.12 и 3.13 - фокус на улучшении уже существующего функционала. Большое количество багфиксов, небольших правок API, попытки немного улучшить производительность, чистка кода и удаление устаревшего. Даже известная плохая документация argparse стала лучше.
Спустя годы преследования новых фич с асинхронностью, типизацией, моржовым оператором и несколькими интерпретаторами, я ожидал от новых людей в команде разработки лишь увеличения этой тенденции. Но вместо этого мы получили улучшения сообщений об ошибках, улучшенный PDB, более гибкий парсер, улучшенный REPL и так далее.
И для меня это знак, что им не все равно.
Автор: MrPizzly
Источник [54]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/changelog/401949
Ссылки в тексте:
[1] release notes: https://www.python.org/downloads/release/python-3130/?featured_on=pythonbytes
[2] RealPython есть хорошая статья: https://realpython.com/python313-new-features/#a-random-command-line
[3] введение в него: https://www.bitecode.dev/p/intro-to-pdb-the-python-debugger
[4] исправили: https://github.com/SonicField/cpython/commit/75c1dc29b7a14dfa80b1931361e70dada2a14735
[5] многострочное редактирование: https://github.com/python/cpython/issues/103124
[6] Автозаполнение кода: https://github.com/python/cpython/issues/112948
[7] использование dotted path: https://github.com/python/cpython/issues/117618
[8] Поддержка pdb в zipapps: https://github.com/python/cpython/issues/118500
[9] Исправили проглатывание аргументов в pdb CLI: https://github.com/python/cpython/issues/113548
[10] pdbrc наконец‑то не сломан: https://github.com/python/cpython/issues/90095
[11] Режим post‑mortem работает даже для SyntaxError: https://github.com/python/cpython/issues/84583
[12] shutil: https://docs.python.org/3/library/shutil.html
[13] много: https://github.com/python/cpython/issues/79513
[14] много: https://bugs.python.org/issue?@action=redirect&bpo=37260
[15] багов: https://github.com/python/cpython/issues/89727
[16] было: https://github.com/python/cpython/issues/116401
[17] исправлено: https://github.com/python/cpython/issues/113188
[18] некоторые: https://github.com/python/cpython/issues/62308
[19] опции: https://github.com/python/cpython/issues/70978
[20] zipfile.Path: https://docs.python.org/3/library/zipfile.html
[21] pathlib: https://docs.python.org/3/library/pathlib.html
[22] получила: https://github.com/python/cpython/issues/115060
[23] много: https://github.com/python/cpython/issues/117727
[24] небольших: https://github.com/python/cpython/issues/117607
[25] оптимизаций: https://github.com/python/cpython/issues/117586
[26] производительности: https://github.com/python/cpython/issues/112855
[27] известная проблема: https://www.youtube.com/watch?v=qiZyDLEJHh0
[28] теперь возвращает: https://bugs.python.org/issue?@action=redirect&bpo=33533
[29] корутина будет закрыта: https://github.com/python/cpython/issues/116720
[30] может быть явно закрыта: https://github.com/python/cpython/issues/96471
[31] было увеличено выше 62: https://github.com/python/cpython/issues/89240
[32] тот самый человек из треда на Reddit: https://www.reddit.com/r/homelab/comments/ksl1h8/high_corecount_server_recommendation/
[33] списков: https://github.com/python/cpython/pull/118160
[34] лямбда‑функций: https://github.com/python/cpython/pull/118019
[35] Улучшения производительности не такие высокие: https://en.lewoniewski.info/2024/python-3-12-vs-python-3-13-performance-testing/
[36] упоминал: https://www.bitecode.dev/p/whats-up-python-38-dies-313-is-born
[37] отменены: https://github.com/python/cpython/issues/124567
[38] больше не могут: https://github.com/python/cpython/issues/83863
[39] вы знаете: https://xkcd.com/1172/
[40] больше не поддерживается: https://github.com/python/cpython/issues/104690
[41] помечены как устаревшие: https://github.com/python/cpython/issues/56166
[42] Аналогично: https://github.com/python/cpython/issues/93057
[43] Устаревание: https://github.com/python/cpython/issues/117337
[44] теперь игнорируются: https://github.com/python/cpython/issues/113659
[45] были почищены: https://github.com/python/cpython/issues/108765
[46] добавляет файл .gitignore: https://github.com/python/cpython/issues/83417
[47] будет использовать C-энкодер JSON: https://github.com/python/cpython/issues/95382
[48] ошибки парсинга: https://github.com/python/cpython/issues/113149
[49] Теперь можно добавлять приватные варианты: https://github.com/python/cpython/issues/118650
[50] лучше работает с multiprocessing: https://github.com/python/cpython/issues/83856
[51] Dataclass теперь вызывает exec() один раз на 1 dataclass: https://github.com/python/cpython/issues/109870
[52] теперь создает auditing event: https://docs.python.org/3/library/time.html#time.sleep
[53] может быть ключевым словом: https://github.com/python/cpython/issues/106487
[54] Источник: https://habr.com/ru/companies/beget/articles/856288/?utm_source=habrahabr&utm_medium=rss&utm_campaign=856288
Нажмите здесь для печати.