This media is not supported in your browser
VIEW IN TELEGRAM
Пятница, 19:00. Худшее время для деплоя, но идеальное, чтобы научить твой Python-скрипт извлекать знания из PDF и скармливать их нейронке.
Хватит скармливать LLM гигантские простыни текста в промптах. Пора строить нормальный `Python`-пайплайн с использованием RAG.
На открытом уроке мы разберём:
— использование
— работу с векторными базами данных для быстрого поиска контекста;
— написание кода, который заставит бота отвечать на вопросы по вашим файлам.
Один из спикеров — Алексей Яндутов, ML-инженер в поиске Яндекса.
Это вводное занятие курса «Разработка AI-агентов». Без воды и маркетинговых обещаний. Только код.
Записаться на урок
Хватит скармливать LLM гигантские простыни текста в промптах. Пора строить нормальный `Python`-пайплайн с использованием RAG.
На открытом уроке мы разберём:
— использование
LangChain и LlamaIndex для связки документов и модели;— работу с векторными базами данных для быстрого поиска контекста;
— написание кода, который заставит бота отвечать на вопросы по вашим файлам.
Один из спикеров — Алексей Яндутов, ML-инженер в поиске Яндекса.
Это вводное занятие курса «Разработка AI-агентов». Без воды и маркетинговых обещаний. Только код.
Записаться на урок
❤1😁1
🧪 PyTest: как параметризовать тесты с исключениями
Иногда нужно прогнать разные входные данные и проверить, что в одних случаях код работает, а в других — выбрасывает нужное исключение.
✖️ Делать отдельный тест под каждый кейс — не всегда разумно.
Для этого удобно комбинировать
Подход простой:
🔵 если исключения не ожидается — используется
🔵 если ожидается —
🔵 все сценарии живут в одном параметризованном тесте
Метод описан в документации PyTest и обсуждался на StackOverflow, но на практике о нём знают не все.
Хорошо подходит, когда:
🔵 проверки на исключения однотипные
🔵 не хочется раздувать тестовый набор
🔵 нужно аккуратно покрыть все ветки кода
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека питониста
#буст
Иногда нужно прогнать разные входные данные и проверить, что в одних случаях код работает, а в других — выбрасывает нужное исключение.
✖️ Делать отдельный тест под каждый кейс — не всегда разумно.
Для этого удобно комбинировать
pytest.mark.parametrize с contextlib.nullcontext:
from contextlib import nullcontext as does_not_raise
import pytest
from pytest import raises
@pytest.mark.parametrize(
["x", "y", "expectation"],
[
(3, 2, does_not_raise()),
(0, 1, does_not_raise()),
(1, 0, raises(ZeroDivisionError)),
(1, "0", raises(TypeError)),
],
)
def test_division(x, y, expectation):
with expectation:
x / y
Подход простой:
nullcontextpytest.raises(...)Метод описан в документации PyTest и обсуждался на StackOverflow, но на практике о нём знают не все.
Хорошо подходит, когда:
nullcontext — не самая очевидная часть стандартной библиотеки, но алиас does_not_raise делает намерение теста понятным с первого взгляда.📍 Навигация: Вакансии • Задачи • Собесы
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤3
Please open Telegram to view this post
VIEW IN TELEGRAM
😁21
Скрипты копятся, а ты всё ещё вручную «жаришь» каждый вызов библиотеки?
Это работа в забегаловке. Настоящий Шеф не пишет однотипный код вечно — он проектирует Систему. 🐍
В понедельник, 26 января, стартует интенсив по разработке ИИ-агентов на Python. Мы научим создавать автономные решения, которые закроют бэклог, пока ты занимаешься архитектурой.
В программе:
— мультиагентные системы в
— сложная логика в
—
Записаться на курс
Это работа в забегаловке. Настоящий Шеф не пишет однотипный код вечно — он проектирует Систему. 🐍
В понедельник, 26 января, стартует интенсив по разработке ИИ-агентов на Python. Мы научим создавать автономные решения, которые закроют бэклог, пока ты занимаешься архитектурой.
В программе:
— мультиагентные системы в
CrewAI: делегирование задач и автоматическое ревью;— сложная логика в
LangGraph: управление состоянием и работа с графами;—
tool use интеграция: подключение Python-агентов к твоим БД и внешним сервисам. 🍳Записаться на курс
👍1
Свежий бенчмарк сравнивает основные Python API-фреймворки на реальных PostgreSQL-нагрузках, а не на синтетическом JSON. Сложные запросы, вложенные связи, корректный eager loading для каждого стека — всё как в проде.
разница в производительности схлопывается, как только появляется база данных.
Если на простом JSON разброс достигает ~20×, то на пагинации это уже ~1.7×, а на сложных запросах — всего ~1.3×.
для database-heavy API имеет смысл тратить время на оптимизацию запросов и моделей данных, а не на бесконечный выбор «самого быстрого» фреймворка — при нормальном коде они все почти равны.
🔗 Код, цифры и воспроизводимый сетап: https://clc.to/D47EDw
📍 Навигация: Вакансии • Задачи • Собесы
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤2
📚Напоминаем про наш полный курс «Самоучитель по Python для начинающих»
Мы написали и собрали для вас в одну подборку все 25 глав и 230 практических заданий!
🐍 Часть 1: Особенности, сферы применения, установка, онлайн IDE
🐍 Часть 2: Все, что нужно для изучения Python с нуля – книги, сайты, каналы и курсы
🐍 Часть 3: Типы данных: преобразование и базовые операции
🐍 Часть 4: Методы работы со строками
🐍 Часть 5: Методы работы со списками и списковыми включениями
🐍 Часть 6: Методы работы со словарями и генераторами словарей
🐍 Часть 7: Методы работы с кортежами
🐍 Часть 8: Методы работы со множествами
🐍 Часть 9: Особенности цикла for
🐍 Часть 10: Условный цикл while
🐍 Часть 11: Функции с позиционными и именованными аргументами
🐍 Часть 12: Анонимные функции
🐍 Часть 13: Рекурсивные функции
🐍 Часть 14: Функции высшего порядка, замыкания и декораторы
🐍 Часть 15: Методы работы с файлами и файловой системой
🐍 Часть 16: Регулярные выражения
🐍 Часть 17: Основы скрапинга и парсинга
🐍 Часть 18: Основы ООП – инкапсуляция и наследование
🐍 Часть 19: Основы ООП – абстракция и полиморфизм
🐍 Часть 20: Графический интерфейс на Tkinter
🐍 Часть 21: Основы разработки игр на Pygame
🐍 Часть 22: Основы работы с SQLite
🐍 Часть 23: Основы веб-разработки на Flask
🐍 Часть 24: Основы работы с NumPy
🐍 Часть 25: Основы анализа данных с Pandas
Мы написали и собрали для вас в одну подборку все 25 глав и 230 практических заданий!
🐍 Часть 1: Особенности, сферы применения, установка, онлайн IDE
🐍 Часть 2: Все, что нужно для изучения Python с нуля – книги, сайты, каналы и курсы
🐍 Часть 3: Типы данных: преобразование и базовые операции
🐍 Часть 4: Методы работы со строками
🐍 Часть 5: Методы работы со списками и списковыми включениями
🐍 Часть 6: Методы работы со словарями и генераторами словарей
🐍 Часть 7: Методы работы с кортежами
🐍 Часть 8: Методы работы со множествами
🐍 Часть 9: Особенности цикла for
🐍 Часть 10: Условный цикл while
🐍 Часть 11: Функции с позиционными и именованными аргументами
🐍 Часть 12: Анонимные функции
🐍 Часть 13: Рекурсивные функции
🐍 Часть 14: Функции высшего порядка, замыкания и декораторы
🐍 Часть 15: Методы работы с файлами и файловой системой
🐍 Часть 16: Регулярные выражения
🐍 Часть 17: Основы скрапинга и парсинга
🐍 Часть 18: Основы ООП – инкапсуляция и наследование
🐍 Часть 19: Основы ООП – абстракция и полиморфизм
🐍 Часть 20: Графический интерфейс на Tkinter
🐍 Часть 21: Основы разработки игр на Pygame
🐍 Часть 22: Основы работы с SQLite
🐍 Часть 23: Основы веб-разработки на Flask
🐍 Часть 24: Основы работы с NumPy
🐍 Часть 25: Основы анализа данных с Pandas
1👍2
Flask в 2025: итоги года и состояние экосистемы
Жив ли Flask в эпоху FastAPI? Короткий ответ — да. Длинный — экосистема стала спокойнее, взрослее и менее хайповой.
Claude Code в 2026: гайд для тех, кто ещё пишет код руками
Немного провокационный, но полезный материал о том, как ИИ меняет процесс разработки. После прочтения хочется либо уволиться, либо автоматизировать всё подряд.
CPython — сборка мусора изнутри
Для тех, кто любит знать, что именно происходит под капотом.
Собираем LLM-агента на Python
Практический гайд по созданию AI-агента без лишней теории.
Pandas 3.0 — релиз
21 января 2026 вышел pandas 3.0 — большой апдейт с важными архитектурными изменениями. Обновляться стоит, но сначала лучше прочитать, что именно поменяли, чтобы потом не удивляться внезапным багам.
📍 Навигация: Вакансии • Задачи • Собесы
#свежак
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤1
Завтра стартуем: курс по разработке ИИ-агентов на Python 🐍
Хватит писать однотипные скрипты — начните проектировать автономные системы. Мы разберём создание мультиагентных связок на
👉 Успейте занять место до начала занятий
Хватит писать однотипные скрипты — начните проектировать автономные системы. Мы разберём создание мультиагентных связок на
CrewAI, стейт-менеджмент в LangGraph и интеграцию агентов с API и базами данных.👉 Успейте занять место до начала занятий
😁3
Forwarded from Библиотека задач по Data Science | тесты, код, задания
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Библиотека задач по Data Science | тесты, код, задания
❤2
Python — язык №1 для разработки AI-агентов. Вы в теме?
Весь современный стек (от
Стартуем сегодня в 19:00 МСК.
Программа интенсива:
— глубокий разбор
— работа с
— сквозной проект: создание мультиагентной системы;
— деплой и мониторинг ИИ-решений.
Доступ к материалам на год и живое комьюнити в комплекте.
Занять место в группе
Весь современный стек (от
LangGraph до CrewAI) завязан на Python. Если вы хотите вырасти из обычного бэкендера в AI Engineer, этот курс для вас.Стартуем сегодня в 19:00 МСК.
Программа интенсива:
— глубокий разбор
LangGraph, CrewAI и AutoGen;— работа с
AsyncIO в контексте агентских вызовов;— сквозной проект: создание мультиагентной системы;
— деплой и мониторинг ИИ-решений.
Доступ к материалам на год и живое комьюнити в комплекте.
Занять место в группе
❤🔥2😁2❤1👍1
Туториалы по FastAPI
Серия туториалов о том, как с нуля собрать полноценное веб-приложение на FastAPI.
Будет и JSON API для программного доступа, и HTML-страницы для работы через браузер.
По ходу разбирается:
— база данных с SQLAlchemy
— валидация данных через Pydantic
— полный CRUD
— структура проекта, близкую к продакшену
🔗 Ссылка на уроки
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека питониста
#буст
Серия туториалов о том, как с нуля собрать полноценное веб-приложение на FastAPI.
Будет и JSON API для программного доступа, и HTML-страницы для работы через браузер.
По ходу разбирается:
— база данных с SQLAlchemy
— валидация данных через Pydantic
— полный CRUD
— структура проекта, близкую к продакшену
🔗 Ссылка на уроки
📍 Навигация: Вакансии • Задачи • Собесы
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤2
🐼 Что нового в pandas 3.0 — наш детальный взгляд
Мы уже делились, что вышел pandas 3.0. Сегодня чуть более детально о том, что реально изменилось:
📍Наконец-то убили SettingWithCopyWarning
Тот самый «адский ворнинг» при работе со срезами DataFrame — всё.
В pandas 3 полностью внедрён Copy-on-Write:
— фильтрации больше не копируют данные сразу
— копия создаётся только при мутации
— .copy() после каждого шага больше не нужен
— предупреждение исчезло
👍 Это одно из самых важных UX-улучшений за годы.
📍Новый синтаксис выражений — pandas.col()
Method chaining в pandas всегда выглядел громоздко из-за lambda:
Теперь можно писать как в Polars / PySpark:
📍UDF больше не приговор к «очень медленно»
.apply() раньше = боль и падение производительности.
В pandas 3 появился интерфейс execution engines.
Теперь UDF можно JIT-компилировать:
Код остаётся понятным Python и производительность может быть выше векторизованного варианта.
📍Строки и Arrow
Полного «Arrow внутри pandas» не случилось.
Вместо этого:
— новый dtype: str
— под капотом может быть Arrow или legacy, в зависимости от окружения
— больше совместимости, меньше боли при апгрейде
— но всё ещё 3 разных способа хранить строки
🔗 Подробно с примерами в статье
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека питониста
#буст
Мы уже делились, что вышел pandas 3.0. Сегодня чуть более детально о том, что реально изменилось:
📍Наконец-то убили SettingWithCopyWarning
Тот самый «адский ворнинг» при работе со срезами DataFrame — всё.
В pandas 3 полностью внедрён Copy-on-Write:
— фильтрации больше не копируют данные сразу
— копия создаётся только при мутации
— .copy() после каждого шага больше не нужен
— предупреждение исчезло
📍Новый синтаксис выражений — pandas.col()
Method chaining в pandas всегда выглядел громоздко из-за lambda:
.assign(max_people=lambda df: df.max_people + df.max_children)
Теперь можно писать как в Polars / PySpark:
.assign(max_people=pandas.col("max_people") + pandas.col("max_children"))
📍UDF больше не приговор к «очень медленно»
.apply() раньше = боль и падение производительности.
В pandas 3 появился интерфейс execution engines.
Теперь UDF можно JIT-компилировать:
df.apply(func, axis=1, engine=bodo.jit())
Код остаётся понятным Python и производительность может быть выше векторизованного варианта.
📍Строки и Arrow
Полного «Arrow внутри pandas» не случилось.
Вместо этого:
— новый dtype: str
— под капотом может быть Arrow или legacy, в зависимости от окружения
— больше совместимости, меньше боли при апгрейде
— но всё ещё 3 разных способа хранить строки
🔗 Подробно с примерами в статье
📍 Навигация: Вакансии • Задачи • Собесы
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1
Python для собеседований. Вопрос: В чём разница между *args и **kwargs?
Когда мы пишем функции в Python, чаще всего знаем, сколько аргументов они будут принимать. Но иногда это неизвестно заранее. Именно для таких случаев существуют
Чтобы их понять, сначала разберёмся с двумя базовыми типами аргументов.
(a) Позиционные аргументы (Positional Arguments)
Это аргументы, которые передаются в функцию в определённом порядке:
первый аргумент →
второй аргумент →
Если перепутать порядок:
Python всё равно выполнит вызов, но:
(b) Именованные аргументы (Keyword Arguments)
Здесь мы явно указываем, какому параметру что соответствует. Порядок уже не важен:
Так код читается лучше и снижает риск ошибок.
🔛 Различия
Используется, когда количество входных значений заранее неизвестно.
Ключи — названия, значения — данные.
🔛 Использование вместе:
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека питониста
#буст
Когда мы пишем функции в Python, чаще всего знаем, сколько аргументов они будут принимать. Но иногда это неизвестно заранее. Именно для таких случаев существуют
*args и **kwargs.Чтобы их понять, сначала разберёмся с двумя базовыми типами аргументов.
(a) Позиционные аргументы (Positional Arguments)
Это аргументы, которые передаются в функцию в определённом порядке:
def greet(name, age):
print(f"Hello {name}, you are {age} years old")
greet('Shiva Shankar', 30)
greet('Narayanan', 32)
первый аргумент →
nameвторой аргумент →
ageЕсли перепутать порядок:
greet(31, 'Lakshmi')
Python всё равно выполнит вызов, но:
name = 31age = 'Lakshmi', что логически неверно.(b) Именованные аргументы (Keyword Arguments)
Здесь мы явно указываем, какому параметру что соответствует. Порядок уже не важен:
greet(name='Ganesh', age=25)
greet(age=21, name='Karthikeya')
Так код читается лучше и снижает риск ошибок.
*args позволяет функции принимать любое количество позиционных аргументов. Внутри функции они собираются в кортеж:
def calculate_total(*prices):
total = 0
for i, price in enumerate(prices, 1):
print(f"Item {i}: {price}")
total += price
print(f"Total: {round(total, 2)}")
calculate_total(10.5, 20, 5.75)
prices → это кортеж: (10.5, 20, 5.75)Используется, когда количество входных значений заранее неизвестно.
**kwargs позволяет принимать любое количество именованных аргументов. Внутри функции они собираются в словарь:
def show_order(**kwargs):
total = 0
for i, (item, price) in enumerate(kwargs.items(), 1):
print(f"{i}. {item}: {price}")
total += price
print(f"Total: {round(total, 2)}")
show_order(apple=2.5, milk=1.8, bread=2.2)
kwargs:
{'apple': 2.5, 'milk': 1.8, 'bread': 2.2}
Ключи — названия, значения — данные.
*args + **kwargs
def shopping_cart(*items, **prices):
print("Items:")
for i, item in enumerate(items, 1):
print(f"{i}. {item}")
print("\nPrices:")
total = 0
for i, (item, price) in enumerate(prices.items(), 1):
print(f"{i}. {item}: {price}")
total += price
print(f"\nTotal bill: {round(total, 2)}")
shopping_cart(
"Shoes", "T-shirt",
Shoes=50, Tshirt=20
)
items → позиционные данные (что купили)prices → именованные данные (цены)📍 Навигация: Вакансии • Задачи • Собесы
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤8🔥3
🎉 Python 1.0 был выпущен ровно 32 года назад!
📅 Точная дата выхода версии 1.0 зафиксирована в архивных анонсах — январь 1994 (релиз 1.0.0 датирован перепиской от 27 января).
В Python 1.0 появились основы, которые мы до сих пор используем — включая механизмы функционального программирования вроде lambda, map, filter и reduce.
Уже тогда язык отличался простотой и читаемостью, что помогло ему быстро найти аудиторию среди разработчиков.
🥳 Так, 27 января 1994 → 27 января 2026 — ровно 32 года Python в строю!
Поздравляем? А сколько вы уже вместе с Python?
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека питониста
#буст
📅 Точная дата выхода версии 1.0 зафиксирована в архивных анонсах — январь 1994 (релиз 1.0.0 датирован перепиской от 27 января).
В Python 1.0 появились основы, которые мы до сих пор используем — включая механизмы функционального программирования вроде lambda, map, filter и reduce.
Уже тогда язык отличался простотой и читаемостью, что помогло ему быстро найти аудиторию среди разработчиков.
🥳 Так, 27 января 1994 → 27 января 2026 — ровно 32 года Python в строю!
Поздравляем? А сколько вы уже вместе с Python?
📍 Навигация: Вакансии • Задачи • Собесы
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
🎉26👍6🤩1
Python — база для ИИ-агентов. Пора выходить за рамки FastAPI и Pandas
Агентские фреймворки вроде
Курс «Углубленные AI-агенты» научит вас строить такие системы с нуля.
Ваш стек на курсе:
—
— глубокая работа с
— создание кастомных
— внедрение RAG-пайплайнов;
— финальный проект для портфолио за 60 дней.
Обучение уже началось, успейте занять место.
🚀 Записаться на основной курс
Если сомневаетесь — просто посмотрите вводное занятие.
Агентские фреймворки вроде
LangGraph и CrewAI меняют правила игры. Теперь ваша задача не просто написать скрипт, а создать среду, где агенты на Python сами управляют логикой и кодом.Курс «Углубленные AI-агенты» научит вас строить такие системы с нуля.
Ваш стек на курсе:
—
Python как дирижер мультиагентных систем;— глубокая работа с
CrewAI, LangGraph и AutoGen;— создание кастомных
Tools для выполнения действий в коде;— внедрение RAG-пайплайнов;
— финальный проект для портфолио за 60 дней.
Обучение уже началось, успейте занять место.
🚀 Записаться на основной курс
Если сомневаетесь — просто посмотрите вводное занятие.
❤2
🚨 Баг на ровном месте: как
Недавно наткнулись на очень показательный баг в Python-проекте с распределёнными процессами.
Один алгоритм считает числовые пороги (`float`) и передаёт их другому процессу в виде JSON. Модели общие, всё на Pydantic — красота, типизация, валидация.
И вдруг второй процесс падает с ошибкой:
>
Хотя первый процесс отправлял… float.
🧩 Что произошло
В одном из порогов оказалось значение NaN:
🧩 Почему
Потому что:
— В IEEE 754 у float есть спецзначение
— В JSON стандарте — нет представления для NaN
— Разрешены только: число, строка, объект, массив,
Поэтому сериализатор делает единственное, что может — превращает
А дальше:
И Pydantic получает:
Но поле объявлено как
То есть:
Сериализация и десериализация не являются обратными операциями.
🧩 Почему это особенно коварно
И у него особая логика:
А вот
🧩 Как это чинить
1. Можно сказать Pydantic сериализовать
Работает идеально внутри Python.
Но многие парсеры (JS, БД, API) такой JSON не примут, и формально это уже не RFC-совместимый JSON.
2. Сделать поле
JSON становится валидным. Но теперь теряется типовая строгость и нужно везде помнить, что
3. Кастомный тип (самый аккуратный)
Сказать модели явно:
>
Теперь:
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека питониста
#буст
NaN превратился в None и сломал PydanticНедавно наткнулись на очень показательный баг в Python-проекте с распределёнными процессами.
Один алгоритм считает числовые пороги (`float`) и передаёт их другому процессу в виде JSON. Модели общие, всё на Pydantic — красота, типизация, валидация.
И вдруг второй процесс падает с ошибкой:
>
Input should be a valid number, input_value=NoneХотя первый процесс отправлял… float.
🧩 Что произошло
В одном из порогов оказалось значение NaN:
thr = Thresholds(high=float('nan'), low=0.0)
json_str = thr.model_dump_json()
print(json_str)
# {"high": null, "low": 0.0}
🧩 Почему
NaN стал nullПотому что:
— В IEEE 754 у float есть спецзначение
NaN— В JSON стандарте — нет представления для NaN
— Разрешены только: число, строка, объект, массив,
true, false, nullПоэтому сериализатор делает единственное, что может — превращает
NaN → null.А дальше:
JSON null → Python None
И Pydantic получает:
high=None
Но поле объявлено как
float, а не float | None → валидация падает.То есть:
float('nan') → JSON null → Python None
Сериализация и десериализация не являются обратными операциями.
🧩 Почему это особенно коварно
NaN — валидный float. Его часто используют как “значение не определено”.И у него особая логика:
nan > 10 # False
nan < 10 # False
nan == 10 # False
А вот
None — это уже другой тип, и сравнения просто падают с TypeError. Семантика теряется.🧩 Как это чинить
1. Можно сказать Pydantic сериализовать
NaN как литерал:
{"high": NaN}
model_config = ConfigDict(ser_json_inf_nan='constants')
Работает идеально внутри Python.
Но многие парсеры (JS, БД, API) такой JSON не примут, и формально это уже не RFC-совместимый JSON.
2. Сделать поле
float | None
high: float | None
JSON становится валидным. Но теперь теряется типовая строгость и нужно везде помнить, что
None на самом деле значит NaN.3. Кастомный тип (самый аккуратный)
Сказать модели явно:
>
null в JSON — это NaN, а не None
FloatNaN = Annotated[
float,
PlainSerializer(lambda v: None if math.isnan(v) else v, when_used="json"),
BeforeValidator(lambda v: float("nan") if v is None else v),
]
Теперь:
NaN → null → NaN
📍 Навигация: Вакансии • Задачи • Собесы
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤7
🐍 Конец эпохи busy-polling в Python: subprocess больше не крутит цикл 15-летней давности
Мало кто задумывается, как Python ждёт завершения процессов. Но начиная с Python 3.3 (когда появился
То есть буквально:
С экспоненциальной паузой, да. Но всё равно это означало:
— постоянные пробуждения CPU
— лишние context switches
— задержку между реальным завершением процесса и моментом, когда Python это замечает
— плохую масштабируемость при большом числе процессов
И так жили около 15 лет.
Выяснилось, что современные POSIX-системы позволяют ждать завершения процесса событийно, без опроса:
🐧 Linux (5.3+)
Появился
Этот FD можно передать в
Ядро само разбудит процесс — никаких циклов, никакого sleep.
🍏 macOS / BSD
Тут есть
🪟 Windows
Тут всё и так было хорошо — используется
Что это даёт на практике
Тест: процесс ждёт сам себя 10 секунд.
До (busy-loop):
После (event-driven):
То есть вместо постоянного «проснулся → проверил → уснул» процесс просто спит в ядре, как при
Меньше CPU, меньше энергопотребление, лучше масштабируемость.
Где это теперь используется
Сначала решение появилось в psutil, а затем попало прямо в CPython subprocess.
Это редкий случай, когда оптимизация из сторонней библиотеки уходит в стандартную библиотеку Python.
Ирония в том, что 15 лет назад
Теперь всё наоборот.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека питониста
#буст
Мало кто задумывается, как Python ждёт завершения процессов. Но начиная с Python 3.3 (когда появился
timeout в `Popen.wait()`), стандартная библиотека использовала… busy-loop polling.То есть буквально:
waitpid(WNOHANG) → sleep → check → sleep → check ...
С экспоненциальной паузой, да. Но всё равно это означало:
— постоянные пробуждения CPU
— лишние context switches
— задержку между реальным завершением процесса и моментом, когда Python это замечает
— плохую масштабируемость при большом числе процессов
И так жили около 15 лет.
Выяснилось, что современные POSIX-системы позволяют ждать завершения процесса событийно, без опроса:
🐧 Linux (5.3+)
Появился
pidfd_open(): он возвращает file descriptor, связанный с PID.Этот FD можно передать в
poll() и просто блокироваться, пока процесс не завершится.Ядро само разбудит процесс — никаких циклов, никакого sleep.
🍏 macOS / BSD
Тут есть
kqueue(), который умеет напрямую следить за PID и уведомлять о EXIT.🪟 Windows
Тут всё и так было хорошо — используется
WaitForSingleObject, то есть событийная модель была с самого начала.Что это даёт на практике
Тест: процесс ждёт сам себя 10 секунд.
До (busy-loop):
Voluntary context switches: 258
После (event-driven):
Voluntary context switches: 2
То есть вместо постоянного «проснулся → проверил → уснул» процесс просто спит в ядре, как при
time.sleep().Меньше CPU, меньше энергопотребление, лучше масштабируемость.
Где это теперь используется
Сначала решение появилось в psutil, а затем попало прямо в CPython subprocess.
Это редкий случай, когда оптимизация из сторонней библиотеки уходит в стандартную библиотеку Python.
Ирония в том, что 15 лет назад
psutil.wait() вдохновлялся реализацией subprocess.wait(timeout=...).Теперь всё наоборот.
📍 Навигация: Вакансии • Задачи • Собесы
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥4❤1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁23🤩1
⚠️ В Python regex лучше использовать `\A...\z`, а не `^...$`
Есть подстава в стандартном модуле
Интуитивно кажется, что шаблон:
должен матчить только строку
Но нет. В Python он матчится и на:
То есть
✅ Правильнее для «строка целиком»
Использовать якоря начала/конца реальной строки:
Это гарантирует, что ни одного лишнего символа, даже
Раньше
Но теперь Python 3.14 добавил поддержку
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека питониста
#буст
Есть подстава в стандартном модуле
re, о которой многие узнают слишком поздно.Интуитивно кажется, что шаблон:
^Hello$должен матчить только строку
"Hello".Но нет. В Python он матчится и на:
"Hello\n"То есть
$ считает позицию перед переводом строки концом строки. И если ты валидируешь ввод, заголовки, токены, протоколы и т.д. — можно случайно пропустить лишний \n.✅ Правильнее для «строка целиком»
Использовать якоря начала/конца реальной строки:
\A — начало всей строки\z — конец всей строки (без поблажек на newline)
\AHello\z
Это гарантирует, что ни одного лишнего символа, даже
\n, нет.Раньше
\z был нормальной практикой почти везде… кроме Python (и JS).Но теперь Python 3.14 добавил поддержку
\z — и он становится универсальным и безопасным вариантом.📍 Навигация: Вакансии • Задачи • Собесы
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤1🤔1