Forwarded from Библиотека дата-сайентиста | Data Science, Machine learning, анализ данных, машинное обучение
21 января 2026 вышел pandas 3.0.
Вот что реально стоит знать 👇
✔️ Строки теперь — не
objectРаньше строки в pandas =
object.Туда можно было засунуть что угодно. Медленно. Неявно. Больно.
Теперь по умолчанию:
pd.Series(["a", "b"]).dtype
# str
Что это даёт:
— dtype только для строк
— единая семантика пропусков (`NaN`)
— лучше память и производительность
Это давно назревшее исправление архитектурной ошибки.
✔️ Copy-on-Write: конец адскому chained assignment
Главное правило pandas 3.0: любой срез — ведёт себя как копия:
df2 = df[df.a > 0]
df2["b"] = 10 # больше НИКОГДА не меняет df
Что изменилось:
—
SettingWithCopyWarning — удалён— «а тут view или copy?» — больше нет
— модифицируешь объект → модифицируй его напрямую
Под капотом pandas всё ещё оптимизирует память. Но API теперь честный.
✔️
pd.col() — выражения без лямбдБыло:
df.assign(c=lambda df: df.a + df.b)
Стало:
df.assign(c=pd.col("a") + pd.col("b"))
✔️ Arrow C Interface — zero-copy будущее
Pandas теперь:
— умеет принимать Arrow-таблицы
— умеет отдавать их без копирования
df.__arrow_c_stream__()
✔️ Новый порядок депрекейтов
Теперь всё прозрачно:
—
Pandas4Warning → сломается в 4.0—
Pandas5Warning → сломается в 5.0⚠️ Совет: обновитесь сначала до 2.3, уберите warning’и — и только потом идите в 3.0.
🔗 Ссылка на релиз
📍 Навигация: Вакансии • Задачи • Собесы
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤5
This media is not supported in your browser
VIEW IN TELEGRAM
🤖 LFM2.5-1.2B-Thinking — бронирует билеты сам
Небольшой Python CLI, который ищет и бронирует авиабилеты через tool calling и reasoning.
✍️ Просто пишешь: «найди самый дешёвый рейс из Барселоны в Белград на 2026-01-31» — и агент сам разбивает задачу на шаги и решает её.
Проект — демо возможностей LFM2.5-1.2B-Thinking: маленькой, но умной модели, заточенной под логические задачи, цепочки действий и вызов инструментов.
👌 И да — она может работать на edge-устройствах.
📱 Проект
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека питониста
#буст
Небольшой Python CLI, который ищет и бронирует авиабилеты через tool calling и reasoning.
✍️ Просто пишешь: «найди самый дешёвый рейс из Барселоны в Белград на 2026-01-31» — и агент сам разбивает задачу на шаги и решает её.
Проект — демо возможностей LFM2.5-1.2B-Thinking: маленькой, но умной модели, заточенной под логические задачи, цепочки действий и вызов инструментов.
👌 И да — она может работать на edge-устройствах.
📍 Навигация: Вакансии • Задачи • Собесы
#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1
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