Zen of Python
19.1K subscribers
1.36K photos
202 videos
38 files
3.49K links
Полный Дзен Пайтона в одном канале

Разместить рекламу: @tproger_sales_bot

Правила общения: https://tprg.ru/rules

Другие каналы: @tproger_channels

Сайт: https://tprg.ru/site

Регистрация в перечне РКН: https://tprg.ru/xZOL
Download Telegram
uv — пакетный менеджер и резолвер зависимостей для Python на Rust. Релиз 0.11.31 опубликован 22 июля и заметно докручивает workspace-сценарии и безопасность установки.

🔘 workspace-источники теперь могут ссылаться по пути на участников другого workspace, а .venv — указывать на централизованные окружения проектов;
🔘 в preview появилась настройка hash-algorithm на уровне конкретного индекса при генерации lockfile;
🔘 у uv audit — параметры audit.malware-check и audit.malware-check-url;
🔘 установщик отклоняет wheel и source-архивы, у которых имя пакета не совпадает с заявленным, включая обход через symlink-пути;
🔘 uv больше не повторяет запросы после ошибок проверки TLS-сертификата и вычищает учётные данные из ошибок Git fetch;
🔘 резолвер избавился от квадратичной работы при дедупликации транзитивных конфликтов.

Централизованные окружения через .venv-ссылку выглядят как шаг к «одна машина — один кэш окружений». Держите .venv в каждом проекте или уже пробовали выносить окружения в одно место?

@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
4
OpenCode: ИИ-агент для Python в терминале, который не уводит код в облако

Если вы предпочитаете командную строку графическим IDE, OpenCode может оказаться удобнее: он работает как TUI прямо в консоли, понимает контекст Python-проекта и рефакторит код с учётом всей кодовой базы, а не вставленного фрагмента.

Для питониста тут два полезных момента. Первый — локальность: провайдер подключается из вашей среды, файлы остаются на вашей машине. Второй: встроенный Pyright и режимы Plan/Build, которые либо показывают план правок, либо применяют его сразу. Ещё AGENTS.md позволяет явно прописать правила проекта: от стиля до команд запуска.

Для старта достаточно бесплатного ключа Gemini. Подробности в обзоре.
3
OpenCode: ИИ-агент для Python в терминале, который не уводит код в облако

Если вы предпочитаете командную строку графическим IDE, OpenCode может оказаться удобнее: он работает как TUI прямо в консоли, понимает контекст Python-проекта и рефакторит код с учётом всей кодовой базы, а не вставленного фрагмента.

Для питониста тут два полезных момента. Первый — локальность: провайдер подключается из вашей среды, файлы остаются на вашей машине. Второй: встроенный Pyright и режимы Plan/Build, которые либо показывают план правок, либо применяют его сразу. Ещё AGENTS.md позволяет явно прописать правила проекта: от стиля до команд запуска.

Для старта достаточно бесплатного ключа Gemini. Подробности в обзоре.
🙈32
В pyvenv.cfg предлагают записывать версию Python — появился PEP 838

Версию интерпретатора в pyvenv.cfg каждый инструмент записывает по-своему: где-то это поле version, где-то version_info, причём с patch-версией, которая устаревает после обновления интерпретатора. PEP 838, созданный 15 июля, предлагает навести здесь порядок к Python 3.16.

🔘 новый ключ python-version записывает только major и minor, например 3.16 — patch-обновления его не ломают;
🔘 создатели окружений должны будут писать python-version, чтение старых полей предлагается считать нежелательным;
🔘 интерпретатор сможет отказаться запускаться из окружения, если major/minor не совпадают;
🔘 окружения без нового ключа разрешено обрабатывать по старым полям или проверять через сам интерпретатор.

Автор PEP — Константин Шютце, референсные реализации уже перечислены для uv, virtualenv и CPython. Статус пока Draft.

Ловили ситуацию, когда venv молча работал с другой версией Python, чем ожидалось?

@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
3
Robot Framework — фреймворк тестовой автоматизации на Python с keyword-driven синтаксисом. Первая бета версии 7.5 вышла 17 июля и открывает новый feature-цикл.

🔘 Libdoc понимает Markdown, а аргументы, возвращаемые значения и исключения можно документировать в Google Style — результат конвертируется в HTML;
🔘 тесты и tasks можно встраивать в Markdown-файлы через fenced-блоки robotframework, файлы .robot.md распознаются автоматически;
🔘 пользовательские console loggers регистрируются через --console и используют API listeners, Rebot поддерживает тот же механизм;
🔘 TimeoutExceeded теперь наследуется от BaseException — случайный except Exception: его больше не проглотит;
🔘 объявлены устаревшими встроенный Testdoc и неоднозначные tag patterns вроде XORY.

Пишете автотесты на Robot Framework или в вашей команде победил чистый pytest?

@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
👎21
Видеофайл на 50 КБ может выполнить код на вашем устройстве

В FFmpeg нашли 16-летнюю уязвимость PixelSmash. Она живёт в декодере MagicYUV: AVI, MKV или MOV размером с картинку вызывает запись за пределами буфера и открывает удалённое выполнение кода. Серьёзность: 8.8 из 10 по шкале CVSS, то есть «высокая».

MagicYUV включён везде по умолчанию «для вашего удобства». Поэтому плееры, мессенджеры, NAS и облачные транскодеры принимают вредоносное видео без вопросов, лишь бы система сгенерировала превью.

Проверьте себя командой из материала: если в выводе есть magicyuv, обновите FFmpeg или пересоберите с флагом --disable-decoder=magicyuv. За 16 лет она успела разойтись повсюду.
😱42
18 июля вышла последняя запланированная бета Python 3.15: около 298 исправлений, сборок и правок документации с прошлой беты. Дальше по плану релиз-кандидат 4 августа.

Что приедет в 3.15:

🔘 PEP 810 — явные ленивые импорты ради быстрого старта;
🔘 PEP 814 добавляет встроенный тип frozendict, а PEP 661 — тип sentinel;
🔘 PEP 799 приносит отдельный пакет для профилирования и Tachyon, семплирующий профилировщик высокой частоты;
🔘 PEP 686 делает UTF-8 кодировкой по умолчанию;
🔘 PEP 831 включает фреймовые указатели по умолчанию, чтобы системные профилировщики видели стек Python;
🔘 JIT заметно подтянули: 8–9% среднего геометрического прироста на x86-64 Linux против обычного интерпретатора и 12–13% на AArch64 macOS против интерпретатора с хвостовыми вызовами;
🔘 официальные 64-битные сборки под Windows перешли на интерпретатор с хвостовыми вызовами, а сборки под macOS теперь ставят поддержку свободной от GIL версии по умолчанию.

Команда просит библиотеки протестироваться на бете и выложить пререлизные колёса, но обычные прод-релизы советует придержать до 3.15.0rc1: ABI после четвёртой беты меняться не должен, гарантий до кандидата всё же нет.

Уже гоняли свои проекты на 3.15 или ждёте финального релиза 1 октября?

@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
FastAPI выпустил три релиза за четыре дня, и все про одно: сколько памяти съедает система зависимостей.

Началось с разбора от пользователя, который собрал приложение с цепочкой из ста вложенных Depends и эндпоинтами на десятки параметров. Реальные проекты с большими графами зависимостей выглядят похоже, только менее наглядно.

🔘 в 0.140.0 от 24 июля класс Dependant разгрузили: вспомогательные функции с кешами вынесли наружу, объект теперь просто хранит данные. Бенчмарк памяти на графе зависимостей упал с 17,5 МБ до 1,1 МБ;
🔘 в 0.140.1 от 27 июля предел lru_cache для классификации вызываемых объектов подняли с 1024 до 4096: нашлись приложения, где зависимостей заметно больше тысячи, а на переполненном кеше выигрыш терялся;
🔘 в 0.140.2 в тот же день перестали удерживать плоские деревья зависимостей: бенчмарк графа маршрута ужался с 575 до 110,7 КБ.

Заодно в CI добавили замер памяти, так что рост потребления теперь виден прямо в пул-реквесте, а не в проде через полгода.

Замеряете память своих сервисов в CI или ловите такое уже на боевых машинах?

@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
52👏1
Донхи На и Никита Соболев предложили PEP 841: запись f{1, 2, 3} создаёт frozenset, f{'a': 1} создаёт frozendict, f{} даёт пустой frozendict. Черновик написан 16 июля, обсуждение открыли 20 июля, целятся в Python 3.16.

Сейчас frozenset({1, 2, 3}) сначала собирает обычное множество, потом копирует его в неизменяемое, и на каждом выполнении ищет имя frozenset в области видимости. Соптимизировать это компилятор не может: имя могут переопределить, а у вызова могут быть побочные эффекты. Один частный случай CPython уже спрямляет, но только справа от in. Присвойте тот же литерал переменной, и оптимизация исчезает.

Что предлагает PEP:

🔘 неизменяемость гарантирует сама грамматика, поэтому её не приходится выводить из того, как значение используется дальше;
🔘 константный f{...} сворачивается в один LOAD_CONST и попадает в .pyc, так что на каждом следующем выполнении конструирование бесплатно;
🔘 добавляются токен FLBRACE, четыре узла AST и две инструкции байткода: BUILD_FROZENSET и BUILD_FROZENMAP;
🔘 работают и генераторные выражения: f{x for x in xs}, f{k: v for k, v in items}, а также распаковка f{*xs} и f{**d};
🔘 f{ сегодня синтаксическая ошибка, поэтому старый код ничего не теряет. Запись f {1} с пробелом ошибкой и останется, путаницы с f-строками нет;
🔘 в стандартной библиотеке авторы насчитали около 105 вызовов frozenset и 65 вызовов frozendict, из них 46 и 22 можно переписать новой записью.

Большая цель за синтаксисом — подтолкнуть людей к неизменяемым контейнерам перед эпохой сборок без GIL и субинтерпретаторов: субинтерпретаторы уже делят между собой frozenset, на очереди frozendict. Про JIT авторы намеренно ничего не обещают, потому что руководящий совет в июне запретил новую разработку JIT в main до принятия отдельного PEP.

Читается ли f{1, 2, 3} лучше, чем frozenset({1, 2, 3}), или лишний префикс только запутает?

@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
12🔥2😍2
Сервис убивало по нехватке памяти каждые несколько часов, но утечки в нём не было

RSS рос ступенями: 620 МБ, 890 МБ, 1,4 ГБ, 2,3 ГБ, 3,1 ГБ. Трафик, загрузка процессора и p99 при этом стояли ровно. Число объектов Python не увеличивалось, ни разбухшего словаря, ни списка, ни кэша найти не удалось. gc.collect() честно собирал циклический мусор, а RSS после него почти не опускался. Сакшам Шарма разобрал этот случай 8 июля.

Дело в разделении обязанностей. Сборщик мусора решает, какие объекты ещё достижимы, а аллокатор решает, вернутся ли освободившиеся страницы операционной системе. Освобождённый объект просто уходит обратно в кучу процесса, и пока в той же странице памяти лежит хоть один живой объект, отдать её ядру нельзя. У glibc malloc к этому добавляются кэш освобождённых блоков tcache и отдельные арены на каждый поток, так что многопоточный сервис держит несколько независимых запасов. В одном из примеров автора живые объекты занимали около 700 МБ при RSS около 2,8 ГБ.

🔘 признак, отличающий это от настоящей утечки: tracemalloc показывает стабильный объём, а RSS продолжает расти;
🔘 лечение обошлось без единой правки в коде Python, jemalloc подключается через LD_PRELOAD;
🔘 в продакшене к нему добавили PYTHONMALLOC=malloc и MALLOC_CONF=narenas:2,background_thread:true;
🔘 автор сообщает примерно о вдвое меньшем потреблении оперативной памяти после перехода;
🔘 проверить гипотезу можно и без замены аллокатора, через MALLOC_ARENA_MAX=2 и вызов malloc_trim(0).

Оговорка автора: malloc не универсально лучше встроенного pymalloc, на миллионах мелких объектов выигрыш может оказаться обратным, поэтому замену нужно мерить на своей нагрузке.

Приходилось ловить рост RSS при стабильном числе объектов, и чем в итоге объяснялось?

@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
uv 0.12.0: uv init теперь создаёт проект со сборочной конфигурацией

Astral выпустила uv 0.12.0 28 июля, первый крупный релиз после 0.11.0 в марте. Изменения касаются дефолтов инициализации, проверки хэшей и разбора архивов пакетов.

Раньше uv init создавал плоскую структуру без сборочной системы, и сборочную конфигурацию со структурой src приходилось добавлять отдельно. Теперь проект сразу пригоден для сборки.

🔘 uv init прописывает [build-system] на uv_build, кладёт код в src/<name> и добавляет точку входа в [project.scripts], прежнее поведение возвращает флаг --no-package;
🔘 отклоняются исходные дистрибутивы в форматах .tar.bz2 и .tar.xz, по PEP 625 допустим .tar.gz, старые .zip пока принимаются ради совместимости; заодно запрещены записи со сжатием bzip2 и LZMA внутри wheel;
🔘 wheel, способный перезаписать сам интерпретатор (файлы вида Python, python.py, Python.exe, записи в .data/scripts), больше не устанавливается;
🔘 режим предрелизов по умолчанию сменился с if-necessary-or-explicit на if-necessary, то есть предрелизная версия ставится только когда без неё зависимости не разрешаются;
🔘 директива --require-hashes внутри requirements.txt действительно включает проверку хэшей, а хэши только по MD5 отвергаются, нужен минимум SHA-256;
🔘 строже валидируется pylock.toml: обязателен массив packages, имя файла допустимо только вида pylock.toml или pylock.dev.toml, проверяется размер артефактов.

Авторы пишут, что большинству обновление не потребует правок. Исключение составляют проекты, где зафиксирована верхняя граница сборочного бэкенда: там нужно поднять до uv_build>=0.11.32,<0.13.

У вас в CI uv закреплён конкретной версией или подтягивается последний?

@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
Rust научился ускорять операции с плавающей точкой, сохраняя контроль за точностью

Если вы держите Rust под рукой для кусков, где Python не хватает скорости, в Rust 1.98 появился повод присмотреться. Новый API разрешает компилятору агрессивнее оптимизировать операции с плавающей точкой, но сохраняет контроль за точностью округления. Это значит, что Rust-код, который вызывается из Python, может считать быстрее без привычного компромисса «скорость против корректности».

Раньше в Rust не было стабильного способа управлять этим компромиссом. Теперь можно явно указать компилятору, где безопасно ускорять вычисления, а где важна минимальная погрешность.

Разобрался Itamar Turner-Trauring: если пишете Rust-расширения для Python или интересуетесь, откуда берётся скорость в числовых библиотеках, загляните.
1👍1