Ленивые импорты в Python 3.15: PEP 810 и буст скорости запуска
На PyCon US 2026 высшие чины из Python-мира вкинули инфу про фичи грядущего Python 3.15. В списке — официальные ленивые импорты (PEP 810). Суть: модули грузятся не при старте твоей софтины, а только когда к ним реально обращаются.
Чел раскурил механику и замерил прирост производительности в PyCharm.
Почитать
👉 About Python
На PyCon US 2026 высшие чины из Python-мира вкинули инфу про фичи грядущего Python 3.15. В списке — официальные ленивые импорты (PEP 810). Суть: модули грузятся не при старте твоей софтины, а только когда к ним реально обращаются.
Чел раскурил механику и замерил прирост производительности в PyCharm.
Почитать
Please open Telegram to view this post
VIEW IN TELEGRAM
С IT-вакансиями уже давно не цветочки — реальная «лимонная» свалка, про которую все в курсе. На Хабре не просто ноют, а пробежались по фактам: что из этого дерьма вытекает для соискателей и для тех, кто нанимает.
Автор не разводит сопли, а тащит годные тулзы для разработчиков и эйчаров, чтоб выжить в этом долбаном цирке.
👉 Читать на Хабре
👉 About Python
Автор не разводит сопли, а тащит годные тулзы для разработчиков и эйчаров, чтоб выжить в этом долбаном цирке.
👉 Читать на Хабре
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
Парень раскатал гео-аналитическую платформу с нуля за 2,5 месяца. И да, он юзал AI-разработку. Пальцем в код не тыкал — отдал всё на откуп нейронке, хотя сам сомневался, что её хватит на реальный прод.
«Нутром чую: чем жирнее проект, тем быстрее AI теряет нить и долбится в лимиты», — делится автор. Но хрен там: платформу, на которую в доисторические времена потратили бы годы, вдвоём забацали за 2,5 месяца.
Хочешь разобраться, как это работает и что надо чтобы повторить — курить статью на Хабре: читать далее
👉 About Python
«Нутром чую: чем жирнее проект, тем быстрее AI теряет нить и долбится в лимиты», — делится автор. Но хрен там: платформу, на которую в доисторические времена потратили бы годы, вдвоём забацали за 2,5 месяца.
Хочешь разобраться, как это работает и что надо чтобы повторить — курить статью на Хабре: читать далее
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
⚡️ GPT-5.6 Sol Ultra завалила 50-летнюю гипотезу о циклах
Легендарная задача из теории графов, которую в 1973-м выкатил Дьердь Секереш, наконец-то дождалась. Суть гипотезы: мол, в любом графе без мостов существует такой букет циклов, что каждое ребро входит ровно в два из них. И всё это без шансов на отмазку.
Пару часов назад сотрудник OpenAI дропнул заяву (X): новая GPT-5.6 Sol сварганила доказательство за час, натравив на неё 64 субагента. Файл с решением положили (PDF), но математический бомонд пока молчит — подтверждения нет.
👉 About Python
Легендарная задача из теории графов, которую в 1973-м выкатил Дьердь Секереш, наконец-то дождалась. Суть гипотезы: мол, в любом графе без мостов существует такой букет циклов, что каждое ребро входит ровно в два из них. И всё это без шансов на отмазку.
Пару часов назад сотрудник OpenAI дропнул заяву (X): новая GPT-5.6 Sol сварганила доказательство за час, натравив на неё 64 субагента. Файл с решением положили (PDF), но математический бомонд пока молчит — подтверждения нет.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
Anthropic толкает самоуправляемых агентов
Команда, стоящая за Claude Code, выкатила гайд по loops — это такие паттерны, где агент гоняет свой рабочий цикл по кругу, пока не долбит стоп-сигнал. Суть проста: завязывай с ручным управлением и постепенно отдавай агенту всё больше контроля.
Всего есть 4 типа циклов:
• Агентный — стартует от промпта, вырубается, когда Claude решает, что работа сделана (ручная верификация через SKILL.md).
• Целевой /goal — ты сам задаёшь условие останова, а отдельная модель-оценщик проверяет результат на соответствие.
• Временной /loop или /schedule — агент сам дёргает триггер: норм для рутины и возни с внешними системами.
• Проактивный — выкидывает человека из цепочки, активируется по событию или по расписанию.
Пара советов в довесок: стартуй с самого простого решения, держи код в чистоте, а на ревью подключай второго агента (/code-review). За токенами следи — ставь чёткие условия останова и выбирай модель с умом. Масштаб динамических воркфлоу проверяй на небольшой выборке, а не сразу на всём.
👉 About Python
Команда, стоящая за Claude Code, выкатила гайд по loops — это такие паттерны, где агент гоняет свой рабочий цикл по кругу, пока не долбит стоп-сигнал. Суть проста: завязывай с ручным управлением и постепенно отдавай агенту всё больше контроля.
Всего есть 4 типа циклов:
• Агентный — стартует от промпта, вырубается, когда Claude решает, что работа сделана (ручная верификация через SKILL.md).
• Целевой /goal — ты сам задаёшь условие останова, а отдельная модель-оценщик проверяет результат на соответствие.
• Временной /loop или /schedule — агент сам дёргает триггер: норм для рутины и возни с внешними системами.
• Проактивный — выкидывает человека из цепочки, активируется по событию или по расписанию.
Пара советов в довесок: стартуй с самого простого решения, держи код в чистоте, а на ревью подключай второго агента (/code-review). За токенами следи — ставь чёткие условия останова и выбирай модель с умом. Масштаб динамических воркфлоу проверяй на небольшой выборке, а не сразу на всём.
Please open Telegram to view this post
VIEW IN TELEGRAM
Память под контролем:
Про
Оверхед словаря и мифы
По умолчанию каждый экземпляр держит атрибуты в
- наследование: у родителя нет
- жесткость: нельзя динамически добавить атрибут - ломаются ORM, сериализаторы, половина библиотек
- дебаг: без
Профилирование через pympler
Вместо гаданий - профилирование через
Цифры не врут: видно, где оверхед реально критичен, а где можно забить.
Гибридная модель:
Когда часть объектов динамическая (dataclass с optional полями), добавляем
Жесткие поля - без оверхеда словаря, динамические - через
Что я обычно делаю:
- профилирую не на старте, а когда память реально начинает течь (pympler.muppy, pympler.summary)
- для тысяч объектов - ORM-модели, объекты игр - обязательно
- если dataclass с наследованием -
- никогда не пихаю
Вывод:
__slots__, pympler и гибридные моделиПро
__slots__ пишут часто, но в реальных проектах с сотнями классов можно нарваться. Не всё так радужно.Оверхед словаря и мифы
По умолчанию каждый экземпляр держит атрибуты в
__dict__. Словарь с хеш-таблицей для миллионов объектов - это 50-70% оверхеда. __slots__ фиксирует список атрибутов на уровне класса и убирает __dict__ (если не добавить вручную). Экономия до 40-60%. Но в больших кодовых базах всплывают грабли:- наследование: у родителя нет
__slots__, у наследника есть - __dict__ все равно создается, выигрыша нет- жесткость: нельзя динамически добавить атрибут - ломаются ORM, сериализаторы, половина библиотек
- дебаг: без
__dict__ не увидишь текущие поля экземпляра в отладчике, приходится лезть в классПрофилирование через pympler
Вместо гаданий - профилирование через
pympler. Пример:from pympler import asizeof
class WithSlots:
__slots__ = ('x', 'y')
def __init__(self):
self.x = 10
self.y = 20
class WithoutSlots:
def __init__(self):
self.x = 10
self.y = 20
print(asizeof.asizeof(WithSlots())) # ~72 байта
print(asizeof.asizeof(WithoutSlots())) # ~184 байта
Цифры не врут: видно, где оверхед реально критичен, а где можно забить.
Гибридная модель:
__slots__ + __dict__Когда часть объектов динамическая (dataclass с optional полями), добавляем
__dict__ в __slots__:class FlexibleSlots:
__slots__ = ('id', 'name', '__dict__')
def __init__(self, id, name, **kwargs):
self.id = id
self.name = name
for k, v in kwargs.items():
setattr(self, k, v)
obj = FlexibleSlots(1, 'test', extra_field=42)
print(obj.extra_field) # 42
Жесткие поля - без оверхеда словаря, динамические - через
__dict__. Памяти чуть больше, но гибкость остается.Что я обычно делаю:
- профилирую не на старте, а когда память реально начинает течь (pympler.muppy, pympler.summary)
- для тысяч объектов - ORM-модели, объекты игр - обязательно
__slots__- если dataclass с наследованием -
@dataclass(slots=True) (Python 3.10+), но контролирую дерево наследования- никогда не пихаю
__slots__ в классы, которые подмешиваются через MRO или передаются в гибкие фреймворкиВывод:
__slots__ - мощный инструмент для сокращения памяти, но его применение требует профилирования и осознанного проектирования, особенно при наследовании и в гибридных сценариях с __dict__.This media is not supported in your browser
VIEW IN TELEGRAM
💀 — 2026-й: железяки полезут в медицину, космос и вообще везде, где мы тупим.
😂 — А в реальности 2026-го: ...
👉 About Python
😂 — А в реальности 2026-го: ...
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
django-filter — 26.1
На свет появилась свежая версия django-filter 26.1. Если кратко — это такая штука для Django, с помощью которой ты легко настраиваешь фильтрацию для querysets своих моделей. Без лишней магии.
Забрать можно тут: https://pypi.python.org/pypi/django-filter/
👉 About Python
На свет появилась свежая версия django-filter 26.1. Если кратко — это такая штука для Django, с помощью которой ты легко настраиваешь фильтрацию для querysets своих моделей. Без лишней магии.
Забрать можно тут: https://pypi.python.org/pypi/django-filter/
Please open Telegram to view this post
VIEW IN TELEGRAM
PyPI
django-filter
Django-filter is a reusable Django application for allowing users to filter querysets dynamically.
Кастомный семафор с приоритетами и TTL для асинхронных in-memory кэшей
Стандартный asyncio.Semaphore не учитывает приоритеты задач и не имеет time‑to‑live. В production‑кэшах это приводит к тому, что чтение с высоким приоритетом блокируется фоновой записью, а зависшая задача может навсегда захватить ресурс. Решение — семафор на PriorityQueue с TTL.
Архитектура на heapq и TTL
Внутри используется heapq — вставка и извлечение за O(log n). Каждая задача помещается в очередь с приоритетом, а TTL отсчитывается от момента постановки. Если время истекло — выбрасывается TimeoutError. Освобождается слот — подхватывается самая приоритетная задача. Context manager гарантирует вызов release.
Типичные грабли
Если TTL истёк, будущее (Future) нужно явно вычищать из очереди, иначе оно остаётся мёртвым грузом и накапливает память. Также приоритеты инвертированы: heapq считает минимальное значение наивысшим приоритетом. Поэтому в acquire передаётся отрицательное число, если нужно обратное поведение.
Пример из production
В in‑memory кэше расставлены приоритеты: запись от пользователя — 0, фоновое обновление — 5, чтение — 10. Для чтения установлен короткий TTL — при зависании можно отдать stale данные вместо полной блокировки. Это trade‑off между свежестью и доступностью.
Недостаток и решение
Если очередь большая и приоритеты постоянно высокие, низкоприоритетные задачи могут умирать по TTL повторно. В таких сценариев стоит внедрить dynamic priority aging — со временем повышать приоритет ожидающей задачи. Но для большинства кэшей описанного подхода достаточно.
Вывод: Кастомный семафор с приоритетами и TTL решает конкретные проблемы конкурентного доступа в асинхронных кэшах, но требует аккуратной очистки и осознания trade‑offs при голодании низкого приоритета.
Стандартный asyncio.Semaphore не учитывает приоритеты задач и не имеет time‑to‑live. В production‑кэшах это приводит к тому, что чтение с высоким приоритетом блокируется фоновой записью, а зависшая задача может навсегда захватить ресурс. Решение — семафор на PriorityQueue с TTL.
Архитектура на heapq и TTL
Внутри используется heapq — вставка и извлечение за O(log n). Каждая задача помещается в очередь с приоритетом, а TTL отсчитывается от момента постановки. Если время истекло — выбрасывается TimeoutError. Освобождается слот — подхватывается самая приоритетная задача. Context manager гарантирует вызов release.
Типичные грабли
Если TTL истёк, будущее (Future) нужно явно вычищать из очереди, иначе оно остаётся мёртвым грузом и накапливает память. Также приоритеты инвертированы: heapq считает минимальное значение наивысшим приоритетом. Поэтому в acquire передаётся отрицательное число, если нужно обратное поведение.
Пример из production
В in‑memory кэше расставлены приоритеты: запись от пользователя — 0, фоновое обновление — 5, чтение — 10. Для чтения установлен короткий TTL — при зависании можно отдать stale данные вместо полной блокировки. Это trade‑off между свежестью и доступностью.
@asynccontextmanager
async def acquire(self, priority: int, ttl: float):
future = self._loop.create_future()
heapq.heappush(self._queue, (priority, future))
try:
result = await asyncio.wait_for(future, timeout=ttl)
yield result
except asyncio.TimeoutError:
self._cleanup_expired()
raise
finally: ... # release and pop next
Недостаток и решение
Если очередь большая и приоритеты постоянно высокие, низкоприоритетные задачи могут умирать по TTL повторно. В таких сценариев стоит внедрить dynamic priority aging — со временем повышать приоритет ожидающей задачи. Но для большинства кэшей описанного подхода достаточно.
Вывод: Кастомный семафор с приоритетами и TTL решает конкретные проблемы конкурентного доступа в асинхронных кэшах, но требует аккуратной очистки и осознания trade‑offs при голодании низкого приоритета.
Как прокачать инструменты для кодинг-агента
Чувак из блога mathspp.com снова в деле — гнет свою серию про написание кодинг-агента с нуля. В этот раз речь пойдет о том, как запилить для него реально годные инструменты.
Все подробности — по ссылке: https://mathspp.com/blog/write-a-coding-agent-from-first-principles-better-tools
👉 About Python
Чувак из блога mathspp.com снова в деле — гнет свою серию про написание кодинг-агента с нуля. В этот раз речь пойдет о том, как запилить для него реально годные инструменты.
Все подробности — по ссылке: https://mathspp.com/blog/write-a-coding-agent-from-first-principles-better-tools
Please open Telegram to view this post
VIEW IN TELEGRAM
Mathspp
Write a coding agent from first principles: better tools
Improve the capabilities of your agent by providing it with better tools.
Сборка Python-приложения в единый бинарник: избавляемся от зависимостей от системных библиотек с PyInstaller и staticx
Каждый раз, когда нужно задеплоить Python-приложение не в контейнер, а просто скопировать один файл на сервер, всплывает проблема зависимостей от системных библиотек. PyInstaller собирает бинарник, но он всё равно тащит libc, libssl и другие .so-файлы. На старой Ubuntu или в Docker на scratch это приводит к ошибкам при запуске. Опытные разработчики часто забывают, что статическая сборка решает эту проблему радикально.
Почему одного PyInstaller недостаточно
PyInstaller с флагом --onefile упаковывает Python-интерпретатор и код в один файл, но он динамически линкует системные библиотеки. Проверка через ldd покажет кучу зависимостей. На машине с другой версией glibc или отсутствующей библиотекой (например, libcrypto) приложение упадёт. Это типичная ошибка: разработчик уверен, что бинарник самодостаточен, но на проде получает segfault.
Решение: статическая линковка через staticx
staticx переупаковывает полученный PyInstaller-бинарник, заменяя динамические зависимости на статические. Он встраивает musl libc и делает бинарник полностью независимым от системы. Для этого:
На выходе — бинарник, который запускается на любом Linux с ядром >= 2.6.28. Без Python, без pip, без системных библиотек.
Типичные ошибки и trade-offs
* Размер бинарника: 5-30 МБ вместо 5 МБ. Для большинства серверных задач это приемлемо, но для embedded может быть критично.
* Проблемы с glibc-расширениями: staticx использует musl libc, поэтому старые C-расширения (например, NumPy, некоторые ORM) могут сломаться. Решение — собирать всё в Docker на alpine:latest с musl-dev.
* Динамические ctypes: если в коде используются ctypes для загрузки .so, их нужно вручную добавить через --add-binary, иначе приложение упадёт с тишиной.
* Дебаг: ошибки сложнее диагностировать. Помогает флаг --debug в PyInstaller и strace на скомпилированном бинарнике.
Production-пример: CI/CD деплой в корпоративной сети
Представьте: вы разворачиваете сервис на серверах, где IT-отдел одобряет установку только через внутренний репозиторий, а на копирование одного файла — без ограничений. Вы запускаете в CI:
Копируете service_static на сервер — и он работает сразу, без Python, зависимостей и permission battles. Это особенно ценно для edge-устройств и минималистичных Docker-образов на scratch.
Вывод: staticx превращает PyInstaller-бинарник в truly portable решение, но требует учёта C-расширений и динамических загрузок — без этого сборка будет работать нестабильно на проде.
Каждый раз, когда нужно задеплоить Python-приложение не в контейнер, а просто скопировать один файл на сервер, всплывает проблема зависимостей от системных библиотек. PyInstaller собирает бинарник, но он всё равно тащит libc, libssl и другие .so-файлы. На старой Ubuntu или в Docker на scratch это приводит к ошибкам при запуске. Опытные разработчики часто забывают, что статическая сборка решает эту проблему радикально.
Почему одного PyInstaller недостаточно
PyInstaller с флагом --onefile упаковывает Python-интерпретатор и код в один файл, но он динамически линкует системные библиотеки. Проверка через ldd покажет кучу зависимостей. На машине с другой версией glibc или отсутствующей библиотекой (например, libcrypto) приложение упадёт. Это типичная ошибка: разработчик уверен, что бинарник самодостаточен, но на проде получает segfault.
Решение: статическая линковка через staticx
staticx переупаковывает полученный PyInstaller-бинарник, заменяя динамические зависимости на статические. Он встраивает musl libc и делает бинарник полностью независимым от системы. Для этого:
pyinstaller --onefile --name myapp main.py
pip install staticx
staticx dist/myapp dist/myapp_static
На выходе — бинарник, который запускается на любом Linux с ядром >= 2.6.28. Без Python, без pip, без системных библиотек.
Типичные ошибки и trade-offs
* Размер бинарника: 5-30 МБ вместо 5 МБ. Для большинства серверных задач это приемлемо, но для embedded может быть критично.
* Проблемы с glibc-расширениями: staticx использует musl libc, поэтому старые C-расширения (например, NumPy, некоторые ORM) могут сломаться. Решение — собирать всё в Docker на alpine:latest с musl-dev.
* Динамические ctypes: если в коде используются ctypes для загрузки .so, их нужно вручную добавить через --add-binary, иначе приложение упадёт с тишиной.
* Дебаг: ошибки сложнее диагностировать. Помогает флаг --debug в PyInstaller и strace на скомпилированном бинарнике.
Production-пример: CI/CD деплой в корпоративной сети
Представьте: вы разворачиваете сервис на серверах, где IT-отдел одобряет установку только через внутренний репозиторий, а на копирование одного файла — без ограничений. Вы запускаете в CI:
pyinstaller --onefile --name service main.py
staticx dist/service dist/service_static
Копируете service_static на сервер — и он работает сразу, без Python, зависимостей и permission battles. Это особенно ценно для edge-устройств и минималистичных Docker-образов на scratch.
Вывод: staticx превращает PyInstaller-бинарник в truly portable решение, но требует учёта C-расширений и динамических загрузок — без этого сборка будет работать нестабильно на проде.
This media is not supported in your browser
VIEW IN TELEGRAM
😎 Полный каминг-аут экипажа
🔫 Чувак из Китая под ником «Blyat» решил, что в Танки надо рубиться по-взрослому. Зацени, что он собрал.
Там реальная бригада: механик-водитель, заряжающий и наводчик. Все при деле 😨
👉 About Python
🔫 Чувак из Китая под ником «Blyat» решил, что в Танки надо рубиться по-взрослому. Зацени, что он собрал.
Там реальная бригада: механик-водитель, заряжающий и наводчик. Все при деле 😨
#cyberpunk
Please open Telegram to view this post
VIEW IN TELEGRAM
6× быстрее бинарный поиск: от скомпилированного кода к механической симпатии
Как выжать больше скорости из Python-кода, который считает? Первое, что приходит в голову — алгоритм покруче натянуть, накатить экстеншен на компилируемом языке или параллельность для нескольких ядер CPU раскочегарить. Но что, если и этого мало?
Детали — тут: https://pythonspeed.com/articles/branchless-binary-search/
👉 About Python
Как выжать больше скорости из Python-кода, который считает? Первое, что приходит в голову — алгоритм покруче натянуть, накатить экстеншен на компилируемом языке или параллельность для нескольких ядер CPU раскочегарить. Но что, если и этого мало?
Детали — тут: https://pythonspeed.com/articles/branchless-binary-search/
Please open Telegram to view this post
VIEW IN TELEGRAM
Python⇒Speed
8× faster binary search: from compiled code to mechanical sympathy
Even once you’re using compiled code, there are still opportunities for faster performance by avoiding fighting the CPU.
Ну что, брат, попал я тут в историю. Надо было отсортировать строки в базе, да ещё и зашифрованные. Первая мысль, конечно, как у нормального человека — наверняка есть какой-нибудь стандартный крипто-лайфхак, все так делают. Ну, копнул поглубже... и понял, что облом. Никто тебе готовую таблетку не подсунул. Простого решения там не завезли.
И главный сюрприз: искал я ответ совсем не в том месте, где надо было.
Читать на Хабре
👉 About Python
И главный сюрприз: искал я ответ совсем не в том месте, где надо было.
Читать на Хабре
Please open Telegram to view this post
VIEW IN TELEGRAM
Хабр
Как я решал задачу сортировки зашифрованных строк
TL;DR: В статье описан мой поиск решения задачи сортировки зашифрованных строк без их предварительной расшифровки, а также краткий обзор подходов, которые встретились мне по пути. Проблема...
Ну, запилить генерацию картинок и видео прямо в свой продукт — это можно провернуть локально за один вечер. Но стоит только кому-то кроме тебя этим воспользоваться — и начинается полный ***. Автор на Хабре разжёвал пошаговый гайд, как сделать всё без заморочек с DevOps.
Источник: Habr
👉 About Python
Источник: Habr
Please open Telegram to view this post
VIEW IN TELEGRAM
Хабр
Как добавить генерацию изображений в ваш продукт без DevOps-настроек: пошаговый гайд
Уверен, у многих есть хотя бы один пет-проект, перспективный B2B SaaS, CRM, другими словами — сервис, который когда-нибудь обязательно выстрелит. В процессе разработки у многих стильных, модных и...
Асинхронная сериализация через __getstate__ / __setstate__ и Protocol 5 для zero-copy передачи данных между воркерами
Когда данные летят между воркерами через multiprocessing или распределенные очереди, каждый байт копирования бьет по памяти. Стандартный pickle копирует объекты целиком, но переопределение
Zero-copy через out-of-band буферы
В protocol 5 (Python 3.8+) появляется zero-copy передача через out-of-band буферы. Данные не упаковываются в байтовый поток, а передаются отдельно через shared memory или IPC.
Пример с NumPy
При дампе с protocol=5 данные физически не копируются, а
Где это критично
По умолчанию pickle копирует большие массивы при передаче через Redis, RabbitMQ или multiprocessing.Queue. Два процесса — два полных копирования. Protocol 5 позволяет не копировать, если оба процесса на одной машине.
* data pipelines с NumPy/Pandas, где каждый гигабайт на счету
* дублирование конфигов с тяжелыми данными — сериализуем только параметры
* потоковый парсинг бинарных протоколов
Типичная ошибка и предупреждение
Ошибка: думать, что zero-copy работает везде. Protocol 5 не поддерживается старым Celery с kombu, а out-of-band буферы требуют ручной передачи — они не входят в байтовый поток. На разных машинах zero-copy превращается в обычную копию из-за отсутствия shared memory.
Практический совет
Всегда ставьте
Вывод: Protocol 5 с кастомными методами сериализации дает zero-copy передачу данных между воркерами на одной машине, экономя память и время, но требует контроля совместимости и ручной передачи буферов.
Когда данные летят между воркерами через multiprocessing или распределенные очереди, каждый байт копирования бьет по памяти. Стандартный pickle копирует объекты целиком, но переопределение
__getstate__ / __setstate__ с protocol 5 позволяет избежать лишних копий.Zero-copy через out-of-band буферы
В protocol 5 (Python 3.8+) появляется zero-copy передача через out-of-band буферы. Данные не упаковываются в байтовый поток, а передаются отдельно через shared memory или IPC.
__getstate__ возвращает только словарь метаданных, а __setstate__ восстанавливает объект из буфера.Пример с NumPy
import pickle
import numpy as np
class ZeroCopyArray:
def __init__(self, data):
self.data = data
def __getstate__(self):
return {'shape': self.data.shape, 'dtype': self.data.dtype}
def __setstate__(self, state):
self.shape, self.dtype, self.data = state['shape'], state['dtype'], None
При дампе с protocol=5 данные физически не копируются, а
None в сериализованном виде — expected.Где это критично
По умолчанию pickle копирует большие массивы при передаче через Redis, RabbitMQ или multiprocessing.Queue. Два процесса — два полных копирования. Protocol 5 позволяет не копировать, если оба процесса на одной машине.
* data pipelines с NumPy/Pandas, где каждый гигабайт на счету
* дублирование конфигов с тяжелыми данными — сериализуем только параметры
* потоковый парсинг бинарных протоколов
Типичная ошибка и предупреждение
Ошибка: думать, что zero-copy работает везде. Protocol 5 не поддерживается старым Celery с kombu, а out-of-band буферы требуют ручной передачи — они не входят в байтовый поток. На разных машинах zero-copy превращается в обычную копию из-за отсутствия shared memory.
Практический совет
Всегда ставьте
protocol=pickle.HIGHEST_PROTOCOL. Для критичных сценариев используйте 5-й протокол с правильными __getstate__ / __setstate__. Изучите PEP 574, документацию pickle.Pickler и код dask с cloudpickle — это реальные production-источники.Вывод: Protocol 5 с кастомными методами сериализации дает zero-copy передачу данных между воркерами на одной машине, экономя память и время, но требует контроля совместимости и ручной передачи буферов.
Talk Python to Me: #554 – Верить ли AI в медицине и вопросах долголетия
Свежий эпизод подкаста уже висит в аудио.
Жми сюда: Talk Python to Me: #554: Trustworthy AI in Healthcare and Longevity
👉 About Python
Свежий эпизод подкаста уже висит в аудио.
Жми сюда: Talk Python to Me: #554: Trustworthy AI in Healthcare and Longevity
Please open Telegram to view this post
VIEW IN TELEGRAM
talkpython.fm
Trustworthy AI in Healthcare and Longevity
You ask an AI a question and it answers with total confidence. Most of the time, a confidently wrong answer is just an annoyance. But what if the question is medical, and there's a real patient on the other end? In that world, a hallucination isn't a bug…
Выпуск #743: Stacks & Queues, Django F-Expressions, MCP Clients и другое
В свежем номере Trey Hunner объясняет, как заюзать обычный список Python для стека (LIFO) и deque из collections для очереди (FIFO). Tim Schilling копает Django F-Expression — штука для запросов через ORM, которая реально упрощает жизнь.
Безопасность и инструменты
Endor Labs зарелизил AURI — AI-агент, который через MCP выцепляет уязвимости, секреты и вредоносные зависимости прямо в редакторе. Ещё выкатился курс от Real Python по созданию Python MCP-клиента — для тестов MCP-серверов.
Важные новости
PEP 797 (Shared Object Proxies) отклонили. Django подвезла патчи безопасности 6.0.7 и 5.2.16. PEP 814 (frozendict) приняли — неизменяемые словари вкатят в Python 3.15. Там же появится режим профилирования интерпретатора с ультранизкими накладными расходами для анализа JIT.
👉 About Python
В свежем номере Trey Hunner объясняет, как заюзать обычный список Python для стека (LIFO) и deque из collections для очереди (FIFO). Tim Schilling копает Django F-Expression — штука для запросов через ORM, которая реально упрощает жизнь.
Безопасность и инструменты
Endor Labs зарелизил AURI — AI-агент, который через MCP выцепляет уязвимости, секреты и вредоносные зависимости прямо в редакторе. Ещё выкатился курс от Real Python по созданию Python MCP-клиента — для тестов MCP-серверов.
Важные новости
PEP 797 (Shared Object Proxies) отклонили. Django подвезла патчи безопасности 6.0.7 и 5.2.16. PEP 814 (frozendict) приняли — неизменяемые словари вкатят в Python 3.15. Там же появится режим профилирования интерпретатора с ультранизкими накладными расходами для анализа JIT.
Please open Telegram to view this post
VIEW IN TELEGRAM
Динамический мониторинг утечек памяти: gc.get_objects и tracemalloc
Память нельзя мониторить только статикой. OOM Killer приходит неожиданно, когда забытый lru_cache или циклическая ссылка в asyncio жрут все ресурсы. Решение — фоновый поток, который раз в N секунд снимает срезы
Как работает
Пример production-сбора
Подводные камни
-
-
-
- C-расширения вроде numpy не поддаются мониторингу — учитывай при анализе.
Практический совет
Ставь пороги на 70% от лимита контейнера. Экспортируй метрики в Prometheus через
Вывод: Динамический мониторинг с gc.get_objects и tracemalloc — первый эшелон защиты от утечек, который позволяет поймать аномалию до падения прода.
Память нельзя мониторить только статикой. OOM Killer приходит неожиданно, когда забытый lru_cache или циклическая ссылка в asyncio жрут все ресурсы. Решение — фоновый поток, который раз в N секунд снимает срезы
gc.get_objects и tracemalloc, сравнивает с порогами и шлет алерт.Как работает
gc.get_objects возвращает все отслеживаемые GC объекты. Считаешь количество инстансов своих классов через Counter. tracemalloc дает раскладку по строкам кода — сразу видно, где аллоцируется больше всего. Сравниваешь снимки, ловишь аномальный рост.Пример production-сбора
import gc
import tracemalloc
from collections import Counter
_MEMORY_THRESHOLD = 50 * 1024 * 1024 # 50 MB
_OBJECT_THRESHOLD = 10000
def check_leaks():
alerts = {}
type_counts = Counter(type(o).__name__ for o in gc.get_objects())
for type_name, count in type_counts.items():
if count > _OBJECT_THRESHOLD:
alerts[f"obj_{type_name}"] = count
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')
total_size = sum(stat.size for stat in top_stats[:10])
if total_size > _MEMORY_THRESHOLD:
alerts["memory_total"] = total_size
return alerts
Подводные камни
-
gc.get_objects замораживает GIL. При миллионе объектов пауза ощутима — решай, готов ли к этому в пиковую нагрузку.-
tracemalloc.start() дает оверхед ~20% на аллокации. Отключай в проде, когда не нужен, или включай дозировано.-
tracemalloc не видит объекты, созданные до старта. Запускай сразу после инициализации приложения.- C-расширения вроде numpy не поддаются мониторингу — учитывай при анализе.
Практический совет
Ставь пороги на 70% от лимита контейнера. Экспортируй метрики в Prometheus через
gc.get_count() и tracemalloc.get_traced_memory(). Для глубокой копки используй objgraph на визуализацию ссылок, pympler или memray. Если сработал алерт, бери py-spy или scalene — ищи конкретную причину.Вывод: Динамический мониторинг с gc.get_objects и tracemalloc — первый эшелон защиты от утечек, который позволяет поймать аномалию до падения прода.
Квантование дробит вызов инструментов совсем не так, как рисует BFCL: проверил на MCP-серверах
Что реально происходит с вызовом инструментов после квантования? Замутил бенчмарк QuantMCP — тестил модели на жалких 4 ГБ VRAM, но не на синтетике, а на живых схемах MCP-серверов.
Главная жиза: популярные бенчмарки типа BFCL систематически впаривают фигню — их оценки коррелируют с реальным падением качества с обратным знаком, аж -0.755.
Источник
👉 About Python
Что реально происходит с вызовом инструментов после квантования? Замутил бенчмарк QuantMCP — тестил модели на жалких 4 ГБ VRAM, но не на синтетике, а на живых схемах MCP-серверов.
Главная жиза: популярные бенчмарки типа BFCL систематически впаривают фигню — их оценки коррелируют с реальным падением качества с обратным знаком, аж -0.755.
Источник
Please open Telegram to view this post
VIEW IN TELEGRAM
Хабр
Квантование ломает вызов инструментов не так, как показывает BFCL: проверил на MCP-серверах
Есть простая практическая задача, из-за которой я вообще все это затеял. Вы берете маленькую модель, квантуете ее, чтобы она влезла в ноутбучную видеокарту, и хотите заранее понимать, насколько...