#Python

12 posts

2026-10-14 23:59

Автор: Кирилл Борисов · PyCon Russia 2016


Профилировщик легко находит функции, в которых программа проводит больше всего времени. Трудности начинаются после этого: таблица сообщает, что дорого, но часто не объясняет, как исполнение туда попало и почему этот путь оказался настолько частым.

Кирилл Борисов показывает, как sampling profiling превращает работу программы в набор снимков стека. Вместо инструментирования заранее выбранных функций профайлер периодически фиксирует весь текущий путь вызовов. Такой сбор пропускает короткие события и не даёт точной хронологии, зато меньше вмешивается в выполнение программы и сохраняет контекст: не только работающую функцию, но и цепочку, которая к ней привела.

Проблема в объёме. На реальном приложении быстро появляются тысячи и миллионы стеков, а плоский отчёт сводит их к отдельным строкам. Flame graph агрегирует одинаковые пути и превращает их в интерактивную карту. Ширина блока показывает, в какой доле сэмплов встречался соответствующий стек, а вертикаль сохраняет иерархию вызовов. Поэтому на графике можно увидеть не просто дорогую функцию, а разные маршруты, из которых она была вызвана.

Доклад записан в 2016 году: конкретные Python-инструменты и способы их подключения стоит воспринимать как исторический контекст. Сам подход не устарел — flame graph остаётся одним из основных представлений для sampling и continuous profiling.

Кому смотреть: разработчикам, которые уже запускали профайлер, получали длинную таблицу функций и не понимали, с какого места начинать расследование.

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

Read more →
0
2026-10-07 22:49

Автор: Дмитрий Ходаков · PyCon Russia 2018


В 2015 году команда Авито выбрала Tornado по правильным причинам. Фреймворк был зрелым, выдерживал production-нагрузку и располагал библиотеками для нужных баз данных. На его основе собрали общий шаблон, от которого затем выросли десятки микросервисов.

Через три года сервисы продолжали работать, но изменился сам Python. Нативные async/await и стандартный asyncio сформировали другую модель асинхронного приложения. Tornado тоже развивался, однако за ним тянулись генераторы, глубокие стеки и собственные исторические абстракции. Когда рядом появился aiohttp, прежний разумный выбор начал обходиться дороже нового — хотя формально ничего не сломалось.

Доклад Дмитрия Ходакова полезен в 2026 году именно этой историей. У технологического решения нет вечного преимущества: оно принимается в конкретной экосистеме и может пережить причины, по которым его когда-то выбрали.

Кому смотреть: техническим руководителям и backend-разработчикам, которые поддерживают исправную, но давно выбранную платформу и не понимают, достаточно ли этого для продолжения работы с ней.

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

Read more →
0
2026-09-30 21:48

Автор: Юрий Селиванов · PyCon Russia 2018


Создать конкурентную задачу легко. Гораздо труднее определить, кто отвечает за её завершение, куда уйдёт исключение и что произойдёт с остальными операциями после таймаута.

В 2018 году Юрий Селиванов рассказывал не только о новых возможностях Python 3.7, но и о фундаментальном недостатке раннего asyncio: библиотека позволяла запускать задачи почти из любого места, не заставляя связывать их жизненные циклы. В результате задача могла пережить породивший её код, потерять исключение или оставить незакрытые ресурсы. Решение автор искал в идеях Trio: nursery, supervisors и управляемых областях отмены.

Смотреть этот доклад сейчас особенно интересно. Можно сравнить планы автора с тем, что действительно появилось в Python. Конкретные API изменились и пришли позже, но поставленная проблема оказалась точной: современному async-коду понадобились не новые способы запускать корутины, а структурированное управление ими.

Кому смотреть: Python-разработчикам, которые используют фоновые задачи, таймауты и конкурентные запросы, но ещё полагаются преимущественно на create_task() и gather().

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

Read more →
0
2026-09-23 22:35

Автор: Григорий Петров · MoscowPython


О GIL часто говорят как об одном большом запрете: Python якобы не умеет работать с потоками. Из такого объяснения невозможно понять ни то, почему ограничение появилось, ни то, почему сетевые программы всё же получают пользу от потоков, ни то, какие ошибки GIL предотвращает на самом деле.

Григорий Петров начинает с истории процессов и потоков, а затем постепенно подводит к устройству CPython. Потоки делят память одного процесса, поэтому интерпретатор должен сохранять целостность своих внутренних структур, даже если операционная система переключит выполнение в неудобный момент. GIL даёт право исполнять Python bytecode одному потоку за раз и тем самым упрощает защиту состояния интерпретатора.

Но действие этого ограничения уже, чем кажется. Во время многих блокирующих операций ввода-вывода GIL освобождается, поэтому другие потоки могут продолжать работу. Нативные библиотеки также могут выполнять тяжёлые вычисления вне интерпретатора без удержания GIL. Главное историческое ограничение относится к CPU-bound коду, который исполняет Python bytecode и пытается использовать несколько ядер с помощью потоков.

Важно для 2026 года: доклад описывает стандартную модель CPython с GIL, которая по-прежнему используется по умолчанию. В CPython 3.13 появилась экспериментальная free-threaded сборка, а в Python 3.14 она стала официально поддерживаемой, но осталась опциональной. Поэтому ограничение CPU-bound потоков уже не абсолютно, однако совместимость расширений, накладные расходы и корректность многопоточного кода всё ещё требуют отдельной проверки.

Кому смотреть: Python-разработчикам, которым нужен не очередной совет «используйте процессы», а связная модель того, зачем существует GIL и где проходит граница его влияния.

Из этого можно взять в работу: перед выбором потоков, процессов или async определить, где задача проводит время: в Python bytecode, нативных вычислениях или ожидании ввода-вывода.

Read more →
0
2026-09-16 23:59

Автор: Николай Павлин · «Павлин Шарит — ИТ вместе с Николаем Павлиным»


Поле status отвечает на вопрос, в каком состоянии находится заказ сейчас. Оно не объясняет, какие состояния были допустимы раньше, куда заказ может перейти дальше и что должно произойти при переходе.

Николай Павлин показывает, как вынести эти правила в конечный автомат с помощью Python-библиотеки python-statemachine. Состояния и переходы объявляются отдельно, недопустимые изменения блокируются библиотекой, а действия и условия можно привязать к конкретным переходам жизненного цикла.

Вместо проверок, распределённых по обработчикам и сервисам, получается одна модель процесса. На ней видно, что созданный заказ можно оплатить, оплаченный — передать в обработку, а попытка перескочить через обязательный этап должна завершиться ошибкой. Эту же структуру можно экспортировать в диаграмму и обсуждать не только с разработчиками.

Кому смотреть: Python-разработчикам, у которых правила изменения статуса сущности начали повторяться в разных частях приложения.

Из этого можно взять в работу: выбрать одну сущность с полем status и выписать разрешённые переходы между значениями. Если список нельзя составить без чтения нескольких сервисов, жизненный цикл уже заслуживает отдельной модели.

Read more →
0
2026-09-09 23:56

Автор: Александр Боргардт (duckstax) · Evrone Development


У питонистов есть простое правило: хочешь сделать быстро — пиши нативный код. Это действительно так, когда нативный код пишут опытные C/C++-разработчики. Но те, кто только начинает погружаться в эту область, часто обнаруживают что стало не быстрее, а медленнее. Боргардт объясняет почему — и как это исправить.

Реальный кейс: ML pipeline с видеопотоком, задача — поиск объектов в кадре в реальном времени. На каком-то этапе всё начало тормозить. Расследование привело не к проблеме в алгоритме, а к проблеме на границе Python–C++: неявные накладные расходы при вызове нативного кода из Python.

Кому смотреть: Python-разработчикам, которые пишут или планируют писать C++-расширения — и хотят понять, почему «просто вынести в C++» не всегда означает «стало быстрее».

Из этого можно взять в работу: если пишете C++-модуль для Python и работаете с большими массивами данных — изучите Buffer Protocol (PEP 3118). Это стандартный механизм zero-copy передачи данных между Python и нативным кодом, который поддерживают numpy, bytearray, bytes.

Read more →
0
2026-09-07 23:44

Автор: Даниил Коноваленко (Яндекс Go) · Python Channel · Moscow Python Conf++ 2021


Даниил Коноваленко — backend-разработчик в Яндекс Go. В подразделении несколько сотен микросервисов, треть из них написана на Python. Однажды во время дежурства пришёл алерт: один из сервисов занял 91% памяти. Открыв графики — всё выглядело нормально. Открыв на большем масштабе — характерный паттерн: память растёт линейно и никогда не возвращается. После перезапуска — то же самое. Это и есть утечка.

Доклад — детективная история с реальным production-кейсом. Три акта: как утечка выглядит и как её опознать, откуда они берутся в языке с GC, какие инструменты помогают найти и исправить.

Кому смотреть: backend-разработчикам на Python, которые деплоят сервисы в production и уверены что GC за них всё уберёт. После этого доклада — чуть менее уверены, зато знают что делать.

Из этого можно взять в работу: если у вашего сервиса есть метрика потребления памяти — посмотрите на неё на масштабе нескольких дней. Линейный рост без возврата после GC-цикла — сигнал для расследования, а не повод «накинуть памяти и посмотреть».

Read more →
0
2026-09-02 22:45

Автор: Артём Малышев · Moscow Python Conf 2016


⚠️ Материал 2016 года, Django Channels 1.x. Концептуальный разбор «зачем это нужно» остаётся актуальным. Детали API и конкретные паттерны с тех пор существенно изменились (Channels 2.x переписал архитектуру Channel Layer). Сверяйтесь с актуальной документацией.


Классический Django построен на WSGI — стандарте, появившемся в 2003 году. Его базовый контракт прост: принять запрос, вернуть ответ. Никакой асинхронности, никаких долгоживущих соединений. Это сознательный дизайн для эпохи, когда веб состоял из страниц с новостями и гостевых книг.

Современный веб хочет другого: живой контент без перезагрузки страницы, WebSocket-соединения, уведомления в реальном времени — пользователи не хотят нажимать F5. Django Channels — это ответ на этот запрос: расширение, добавляющее поддержку асинхронных протоколов поверх синхронного фреймворка.

Кому смотреть: Django-разработчикам, которым нужны WebSocket или long-polling, и которые хотят понять как Channels вписывается в Django-архитектуру — особенно где заканчивается синхронный Django и начинается async.

Из этого можно взять в работу: если добавляете real-time функциональность в Django-проект — поймите границу между синхронным Django (models, ORM, middleware) и async Channel Layer до того как начнёте писать код. Смешивать их без понимания этой границы — источник трудноуловимых проблем.

Read more →
0
2026-08-19 22:13

Автор: Григорий Петров и Никита Соболев · MoscowPython


Python Day Special на Positive Hack Days 2025 — формат живой дискуссии за столом, который Moscow Python проводит как спецвыпуск между конференциями. Ведущие — Григорий Петров (евангелист MoscowPython) и Никита Соболев. Тема — асинхронность в Python: не туториал по asyncio, а честный разговор о том, что эта парадигма даёт и чего стоит.

Разговор идёт по структуре: сначала реальные преимущества (07:43), затем реальные недостатки (19:04), затем то о чём обычно не говорят — сложности асинхронного программирования в целом (22:10). Отдельный блок — несовместимость sync и async миров в библиотеках и фреймворках (28:22, 43:55): когда одна синхронная зависимость блокирует весь event loop.

Кому смотреть: Python-разработчикам, которые используют async на практике или только решают, нужен ли он их проекту — и хотят услышать взвешенную оценку, а не «async — это будущее».

Из этого можно взять в работу: проверить, нет ли в вашем async-коде синхронных вызовов в библиотеках без async-поддержки — это одна из самых частых причин, когда async не даёт ожидаемого прироста.

Read more →
0
2026-08-17 23:01

Автор: Александр Морозов (co-founder & CTO, Datafold) · Python Channel · Moscow Python Conf++ 2021


Datafold — стартап из YCombinator, платформа мониторинга аналитических данных. Прошли акселератор, писали MVP за 1–2 месяца — за основу взяли Redash (MIT-лицензия, аналитические БД, SPA). Redash целиком построен на Flask: sqlalchemy, alembic, REST, auth, rate-limiters, CSRF, CLI. Через какое-то время решили менять стек.

Название доклада начинается с «Не highload» — и это принципиально. Причина переезда не в том, что Flask медленный. Причина в том, что типичный Flask-хэндлер — это огромный boilerplate для простых вещей: получить данные из тела запроса как JSON, провалидировать, сконвертировать. Хочешь нормальные сообщения об ошибках — boilerplate вырастает ещё в несколько раз. FastAPI решает это через type hints и Pydantic: код становится короче, читаемее и самодокументируемым.

Кому смотреть: разработчикам на Flask, которые думают о переходе на FastAPI — или уже переходят. Морозов рассказывает не то, что написано в документации, а конкретные проблемы при реальном переезде и как их обошли.

Из этого можно взять в работу: если у вас Flask и вы тратите значительное время на boilerplate для валидации запросов — это именно тот сигнал. FastAPI с Pydantic закрывает эту боль, а не задачу throughput.

Read more →
0
2026-08-10 23:56

Автор: Алексей Фирсов (мейнтейнер aiopg, SoftPro) · MoscowPython


⚠️ Выпуск записан в 2019 году. Детали реализации aiopg и экосистема async-драйверов для PostgreSQL с тех пор изменились (появились asyncpg, sqlalchemy async, psycopg3). Архитектурные решения и вопросы дизайна — актуальны.


Первый выпуск Moscow Python Podcast (переименован из Python Junior Podcast) открылся «хардкором и сеньорностью». Гость: Алексей Фирсов, старший разработчик SoftPro и мейнтейнер библиотеки aiopg. Разговор ведут сооснователь MoscowPython Валентин Домбровский, тимлид NVIDIA Злата Обуховская и Григорий Петров. 44 минуты про то, как устроен асинхронный доступ к PostgreSQL из Python — и зачем вообще нужна отдельная библиотека для этого.

Центральный вопрос выпуска формулируется прямо: так ли уж нужна целая библиотека для взаимодействия асинхронного кода с PostgreSQL (05:32)? Ответ разворачивается через архитектурные детали: aiopg работает поверх psycopg2, который работает поверх написанной на C библиотеки libpq — и при этом сам написан на Python, а не на C. Почему — отдельный разговор (12:36).

Кому смотреть: Python-разработчикам, которые используют или планируют использовать async с PostgreSQL и хотят понять что происходит «под капотом», а не просто вызывать await conn.execute().

Из этого можно взять в работу: проверить в своём async-коде — есть ли места, где coroutine вызывается без await. Python это разрешает, и это источник трудноуловимых багов. Вопрос поднимается в выпуске явно (35:14) как вопрос дизайна языка.

Read more →
0
2026-06-03 23:59

Автор: Артём Шумейко · YouTube


Артём Шумейко — Python-разработчик и преподаватель, специализируется на backend. В коротком видео показывает на живом примере и с реальными цифрами, как FastAPI обрабатывает больше тысячи запросов в секунду.

Асинхронность часто объясняют через «это быстро» — и это неточная формулировка, которая потом мешает. FastAPI не делает CPU-код быстрее. Он устраняет простой: пока один запрос ждёт ответа от базы данных или внешнего сервиса, event loop берёт следующий. При I/O-bound нагрузке это даёт кратный прирост пропускной способности без дополнительных потоков и без накладных расходов на переключение контекста. Видео полезно тем, что показывает разницу измеримо, а не концептуально.

Кому смотреть: Python-разработчикам, которые пишут async/await по инерции или «потому что так принято в FastAPI», но не могут объяснить, почему это работает и когда это не поможет.

Из этого можно взять в работу: найди в своём коде async-функцию, которая делает блокирующий вызов — requests.get() вместо httpx, time.sleep() вместо asyncio.sleep(). Одна такая точка блокирует весь event loop.

Read more →
0