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

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

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

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

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

Регистрация в перечне РКН: https://tprg.ru/xZOL
Download Telegram
Новые модели выходят быстрее, чем все успевают их внедрять, а прогнозы про ИИ устаревают ещё быстрее, поэтому на кафедре техпреда МФТИ запустили «Точку сборки».

Это серия открытых вебинаров, на которых спикеры делятся опытом внедрения агентов, быстрой сборки MVP и конкретными кейсами своих команд.

Больше о «Точке сборки», о первом вебинаре и о том, как попасть на следующие читайте в новом материале на Tproger: https://tproger.ru/articles/pochemu-opyt-razrabotchikov-luchwe-prognozov-pro-ii
1
Технически всё верно...
😁19
Django научился превращать классический N+1 в два запроса без единой правки в коде цикла

Django 6.1 вышел 5 августа. Главное изменение в релизе — режимы дозагрузки полей, то есть настройка того, что происходит в момент обращения к полю, которое из базы не приехало.

Раньше поведение было одно: подтягиваем недостающее поле для этого объекта. Теперь оно называется FETCH_ONE и остаётся по умолчанию, а рядом появились ещё два. FETCH_PEERS подтягивает поле сразу для всех объектов, приехавших из того же запроса, то есть работает как prefetch_related по требованию. FETCH_RAISE запрещает неявные обращения к базе вовсе.

🔘 режим ставится методом QuerySet.fetch_mode(), и цикл, который в каждой итерации трогает внешний ключ, начинает укладываться в два запроса вместо N+1;
🔘 FETCH_RAISE полезен в критичных по скорости участках: любой незамеченный поход в базу превращается в ошибку, а не в тихий лишний запрос;
🔘 у ForeignKey.on_delete появились варианты на стороне базы: DB_CASCADE, DB_SET_NULL и DB_SET_DEFAULT работают через SQL ON DELETE, и объекты для удаления загружать не нужно;
🔘 плата за это честно описана: DB_CASCADE не вызывает сигналы pre_delete и post_delete, потому что Python в удалении не участвует;
🔘 настройка MAILERS позволяет описать несколько почтовых движков с разными параметрами, как это давно сделано для кэшей и баз; в Django 7.0 она заменит EMAIL_BACKEND, пока старая настройка работает с предупреждением;
🔘 число итераций в хешировании паролей PBKDF2 поднято с 1 200 000 до 1 500 000.

По мелочи: добавлены функции UUID4 и UUID7, вычисляемые поля получили виртуальные колонки на PostgreSQL 18 и выше, RedirectView с сохранением метода запроса теперь отвечает кодами 307 и 308 вместо 302 и 301, а OpenLayers в админке обновлён с 7.2.2 до 10.9.0.

Поддерживаются Python 3.12, 3.13 и 3.14. Обычная поддержка релиза продлится примерно до апреля 2027 года, расширенная до декабря. В заметках отдельно перечислены несовместимости, так что перед обновлением их стоит прочитать: смена семантики сигналов при каскадном удалении на стороне базы как раз тот случай, когда код продолжает работать, а побочные действия молча исчезают.

@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
4
У библиотеки websockets появилась реализация на Trio

Версия 17.0 вышла 29 июля. Раньше выбора не было: под капотом всегда asyncio либо потоки. Теперь третий вариант — Trio, для тех, кто уже строит на нём приложение.

Релиз ломающий, и вот что придётся проверить перед обновлением:

🔘 минимальная версия Python поднята до 3.11, последней с поддержкой 3.10 остаётся ветка 16.1;
🔘 удалены псевдонимы модулей, которые перенесли ещё в девятой версии;
🔘 несколько логических аргументов у send(), ping() и broadcast() стали передаваться только по имени;
🔘 не-ASCII заголовки рукопожатия теперь кодируются в ISO-8859-1; прежнее поведение было недокументированным и не совпадало со спецификацией HTTP;
🔘 в реализации на потоках аргумент socket переименован в sock;
🔘 process_request теперь получает и запросы с методом, отличным от GET, и запросы по HTTP/1.0, вместо того чтобы соединение просто закрывалось.

Из добавленного: broadcast() и Server.connections в реализации на потоках, аккуратное закрытие соединений при остановке, reconnect_delays для настройки пауз между попытками переподключения, а на некорректное рукопожатие сервер теперь отвечает кодами 405 и 505 вместо тишины.

@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
3👌1
Ruff включил по умолчанию 413 правил вместо 59

Версия 0.16.0 вышла 23 июля. Заодно 18 самых спорных правил групп pycodestyle и pyflakes из набора по умолчанию убрали.

🔘 форматирование блоков Python внутри Markdown включено по умолчанию — документация в репозитории теперь тоже под форматтером;
🔘 подавляющий комментарий ruff: ignore можно ставить в конце строки, как noqa, или на строке перед диагностикой;
🔘 исправления показываются прямо в выводе check и format --check, вместе с кусочком диффа;
🔘 format --check получил форматы вывода линтера, включая github и gitlab для аннотаций в сборке;
🔘 в JSON-выводе поля filename, location и end_location теперь могут быть null — разборщики придётся проверить;
🔘 стабилизированы двенадцать правил.

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

@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥2
Пять игр на Python, которые интересно почитать: они лежат в репозитории с настройками рабочего окружения Arch, и четыре из пяти обходятся стандартной библиотекой, а две самые большие рисуют интерфейс на curses.

🔘 tetris.py, 766 строк: все повороты фигур считаются заранее в build_rotations, при повороте у стены пробуются сдвиги, есть удержание фигуры и превью следующих, а когда разом уходят четыре линии, по экрану летят частицы;
🔘 snake.py, 423 строки: поле подгоняется под размер терминала, интервал тика уменьшается с каждым уровнем, голова заворачивается через край;
🔘 обе игры печатают через safe_addstr: он глотает curses.error, а в змейке ещё и обрезает строку по краю окна — иначе запись в последнюю ячейку роняет игру;
🔘 рекорды пишутся в общий game_high_scores.json так, чтобы не затирать записи соседних игр;
🔘 tetris_pygame.py — та же игра на pygame и dataclass, удобно сравнить два подхода к одной механике.

@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
12 августа вышли security-релизы Python 3.12.14, 3.11.16 и 3.10.21. Список исправлений длинный, и почти всё в нём про стандартную библиотеку:

🔘 tarfile: несколько обходов фильтра data_filter(), через которые архив мог положить symlink за пределы каталога назначения; один из них — обход прошлогоднего CVE-2025-4330;
🔘 webbrowser.open() отклоняет URL с ведущим дефисом, чтобы аргумент не читался браузером как флаг; закрыт и обход этой проверки через префикс %action;
🔘 HTTPConnection.set_tunnel() больше не пропускает CR/LF в заголовках, wsgiref — управляющие символы в статусе, http.cookies — в Morsel (CVE-2026-3644);
🔘 SourcelessFileLoader открывает .pyc через io.open_code() (CVE-2026-2297), в xml.parsers.expat починен крэш от глубокой вложенности (CVE-2026-4224);
🔘 квадратичное и экспоненциальное поведение убрано из unicodedata.normalize(), html.parser, configparser, ElementTree и csv.Sniffer;
🔘 http.client ограничил число trailer-строк и промежуточных ответов 1xx сотней, чтобы сервер не мог держать клиента вечно.

Все три ветки в стадии security-only: релизы только исходниками, без установщиков. 3.10 получает исправления до октября этого года, 3.12 — до октября 2028-го.

@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
4
У Uvicorn появился разбор HTTP на Zig

Версия 0.52.0 вышла 29 июля и принесла экспериментальную реализацию HTTP/1.1. Работает она на библиотеке zttp: разбор там устроен без собственного ввода-вывода, ядро написано на Zig, а к Python приделаны привязки. Включается новый разборщик параметром --http zttp, схема запуска при этом не меняется.

🔘 сам разборщик перед публикацией несколько недель гоняли под фаззингом и провели несколько раундов проверки безопасности;
🔘 авторы прямо называют его экспериментальным и не советуют пускать через него боевой трафик;
🔘 сравнительных замеров задержки и пропускной способности в заметках нет вообще, так что выигрыш придётся мерить самому;
🔘 отдельно починена обработка заголовков WebSocket с символами вне ASCII в связке с библиотекой websockets версии 17.0;
🔘 в той же версии websockets кодирование таких заголовков переведено на ISO-8859-1, и это как раз причина расхождения;
🔘 обратную связь авторы просят присылать в трекер, то есть релиз рассчитан на тех, кто готов проверять на своей нагрузке.

Замеров ускорения авторы не приводят. Сам приём такой: разбор протокола вынесен в отдельную библиотеку без ввода-вывода, написанную на другом языке, а Python остаётся клеем и сокетным слоем. Проверить новый путь можно на тестовом стенде, ничего не меняя в боевом запуске: старая реализация остаётся на месте и остаётся выбором по умолчанию.

@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
2
Разрешение зависимостей предложили считать задачей для решателя, а не перебором. SMTpip переводит ограничения пакетов и Requires-Python в формулу и отдаёт её weighted Max-SMT, который за один заход выбирает и версии библиотек, и версию интерпретатора. pip вместо этого перебирает кандидатов с откатами.

Что получилось на замерах авторов:

🔘 в среднем по всем наборам ускорение в 6,9 раза против pip, в 9,6 против классического решателя Conda, в 3,2 против smartPip и в 4 против PyEGo;
🔘 на наборе HG2.9K те же 1668 случаев: 433,68 секунды против 2165,20 у pip, ускорение в 4,9 раза;
🔘 доля проектов, которые после установки реально запустились: 87,1% против 75,4% у pip, а на 3081 ноутбуке 39,92% против 20%.

Оговорки авторы приводят сами. Это препринт первой версии; время меряли только для разрешения зависимостей, без скачивания и установки пакетов; из конкурентов брали классический solver Conda, libmamba оставили за рамками. Успешный запуск здесь означает, что программа стартовала, а не что она работает правильно.

@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Почему str.lower() иногда ломает проверку имён доменов

Регистр символа в Python зависит от версии Unicode интерпретатора. Сейчас unicodedata.unidata_version — 17.0.0, а протокол подготовки строк stringprep, который лежит в основе международных доменных имён, зафиксирован на Unicode 3.2.

Поэтому str.lower() и str.encode('idna') в разных версиях Python могут считать разные строки одинаковыми. В обычном коде это проходит незамеченным, а в проверке доменов или авторизации получается обход валидации.

В контексте безопасности не зовите str.lower() напрямую. Берите пакет idna: он реализует стандарт IDNA 2008 и не использует встроенные таблицы Unicode.

Seth Larson разбирает уязвимость и показывает, как это выглядит на практике.
5
Django переходит на один релиз в год. Steering Council принял DEP 20: с января 2028-го выходит один feature-релиз в год, версии называются по году — Django 2028, Django 2029.

🔘 каждый релиз получает три года поддержки: год обычных исправлений и два года security и data-loss fixes; отдельная метка LTS уходит, потому что каждая версия теперь LTS;
🔘 версия поддерживает три последних Python на момент выхода и подхватывает новый Python в первый год; поддержка Django заканчивается вместе с самым старым из них;
🔘 в любой момент поддерживаются три версии, и обновляться можно по одной в год без прыжка через два года изменений;
🔘 политика депрекаций не меняется, в календарных днях сроки только удлиняются.

Переход: Django 6.1 вышел в августе, 6.2 LTS выйдет в апреле 2027-го, Django 2028 — в январе 2028-го. Обязательства по 5.2 LTS и 6.2 LTS остаются как объявлены.

@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🌭1
Cython научился подсказывать компилятору C, какая ветка вероятнее

14 августа вышла бета 3.3.0b1. Релиз для тех, кто собирает расширения: в нём несколько вещей, которые раньше приходилось обходить руками.

🔘 появились cython.likely() и cython.unlikely() — подсказки оптимизатору компилятора C о том, какая ветка условия ожидается чаще;
🔘 реализована конструкция except * для групп исключений по PEP 654 на Python 3.11 и новее;
🔘 аннотации типов у глобальных переменных теперь участвуют в выводе типов, а не игнорируются;
🔘 у сеттеров свойств, объявленных на C, появилась возможность явно пробрасывать исключение вместо безусловной проверки PyErr_Occurred() после каждого вызова;
🔘 поддержан синтаксис однородных кортежей вида tuple[atype, ...];
🔘 набор возможностей общего модуля теперь настраивается при сборке: команда cython generate-shared принимает --only и --exclude, так что в модуль попадает только нужное.

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

Есть и просто ускорения: форматирование чисел в f-строках, extend у bytearray байтами, проверки одиночного символа, размер асинхронных генераторов и перевод модулей с большим числом строк. Численных замеров в списке изменений нет, только слова «быстрее» и «меньше», так что судить о выигрыше на своём проекте придётся самому.

@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥3
⚡️ О!Хакатон возвращается — на кону миллион

Приглашаем Go- и Python-разработчиков, аналитиков и продакт-менеджеров на тревел-тех хакатон от Островка.

Вам предстоит решить одну из двух AI-задач в сфере тревел-теха и побороться за главный приз — 1 000 000 ₽.
Присоединиться к хакатону можно из любой точки мира. Участвуйте командой до пяти человек и выбирайте один из двух треков:

✔️ «О!дин запрос». Цель для junior-специалистов — создать AI-агента для путешествий и отелей.
✔️ «О!дин шаг до идеального отеля». Задача для специалистов уровней middle и senior — «переизобрести» опыт бронирования пользователя с помощью AI и новых интерфейсных механик.

📎 Регистрация открыта до 16 октября 2026 года. Стартуем 23 октября.

Скорее присоединяйтесь по ссылке!
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Двадцать пять минут, которые снимают половину вопросов новичка: доклад Неда Бэтчелдера «Facts and Myths about Python names and values» с PyCon US 2015.

Весь доклад отвечает на один вопрос: что происходит, когда вы пишете x = 23. Ответ — не «в переменную кладётся значение», а «имя привязывается к объекту». Из этого простого сдвига вырастает объяснение почти всех классических непоняток:

🔘 почему Python нельзя описать ни как передачу по значению, ни как передачу по ссылке;
🔘 почему два имени могут указывать на один объект и менять его вместе;
🔘 почему присваивание никогда не копирует объект;
🔘 почему += для списка и для числа ведут себя по-разному;
🔘 почему изменяемый аргумент по умолчанию живёт между вызовами;
🔘 почему аргументы функции, атрибуты объекта и переменная цикла — это всё одна и та же операция связывания имени.

Бэтчелдер разбирает это на диаграммах с коробочками и стрелками, без единой строчки про внутренности интерпретатора. Именно поэтому доклад одиннадцатилетней давности не устарел ни на строчку: семантика имён и объектов с тех пор не менялась.

@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Numba 0.67.0 научилась работать с NumPy 2.5 и собирает пакеты для Python 3.14 и Windows ARM64.

🔘 у np.sum и np.cumsum появился динамический axis, ось теперь можно вычислять во время выполнения;
🔘 добавлена JIT-поддержка np.insert, пока без аргумента axis;
🔘 np.random.binomial в RandomState переключается с BINV на BTPE, когда n * min(p, 1 - p) > 30, поток случайных чисел при этом сохраняется;
🔘 анализ живости переменных перевели на топологический порядок, а проверка принадлежности стеку в _find_back_edges стала за O(1);
🔘 сборки через pycc теперь могут быть побайтно воспроизводимыми на Linux и macOS.

Из ломающего: np.row_stack и двумерное векторное произведение убраны вслед за NumPy 2.5, cross2d остаётся только для старых версий. Пакеты под Windows ARM64 на старте ограничены Python 3.14, часть тестов там пропущена из-за проблемы в LLVM 22.

Отдельно починили тихую ошибку компиляции при повторном присваивании нелокальной переменной во вложенной функции: раньше генерировался неверный код, теперь вылетает UnsupportedError. Численного бенчмарка ускорения BTPE авторы не приводят.

@zen_of_python
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1