Чего не проверяет runtime_checkable Protocol
Protocol позволяет описать небольшой интерфейс: например, метод send(destination, message). Класс может удовлетворять ему без наследования — статический анализатор проверяет совместимость структуры и сигнатур.
Декоратор runtime_checkable добавляет возможность isinstance, но такая проверка не валидирует сигнатуры методов. Наличие атрибута send не доказывает, что он принимает нужные аргументы или выполняет обещанное действие.
Поэтому проверка плагина требует нескольких уровней: типизация помогает проверить код, тест контракта — поведение адаптера, схема — внешние данные. Аннотация quantity: int сама по себе не отвергает отрицательное число, а корректная схема заказа не доказывает, что товар есть на складе.
#python #типизация
Protocol позволяет описать небольшой интерфейс: например, метод send(destination, message). Класс может удовлетворять ему без наследования — статический анализатор проверяет совместимость структуры и сигнатур.
Декоратор runtime_checkable добавляет возможность isinstance, но такая проверка не валидирует сигнатуры методов. Наличие атрибута send не доказывает, что он принимает нужные аргументы или выполняет обещанное действие.
Поэтому проверка плагина требует нескольких уровней: типизация помогает проверить код, тест контракта — поведение адаптера, схема — внешние данные. Аннотация quantity: int сама по себе не отвергает отрицательное число, а корректная схема заказа не доказывает, что товар есть на складе.
#python #типизация
Как измерять время async-функции через декоратор
Обычная обёртка может вызвать async-функцию и получить объект корутины за микросекунды. Это ещё не время запроса: выполнение корутины начнётся позже, а исключение возникнет уже за пределами обёртки.
В разборе async-декораторов обёртка сама объявлена через async def. Она сохраняет время старта, выполняет return await fn(*args, **kwargs), а запись длительности помещает в finally.
Так измерение охватывает выполнение и очистку при ошибке или отмене. functools.wraps сохраняет метаданные и связь wrapped для интроспекции. Сам сборщик метрик тоже должен быть аккуратным: его ошибка в finally способна перекрыть исходное исключение, а блокирующий ввод-вывод задержит весь event loop.
#python #asyncio
Обычная обёртка может вызвать async-функцию и получить объект корутины за микросекунды. Это ещё не время запроса: выполнение корутины начнётся позже, а исключение возникнет уже за пределами обёртки.
В разборе async-декораторов обёртка сама объявлена через async def. Она сохраняет время старта, выполняет return await fn(*args, **kwargs), а запись длительности помещает в finally.
Так измерение охватывает выполнение и очистку при ошибке или отмене. functools.wraps сохраняет метаданные и связь wrapped для интроспекции. Сам сборщик метрик тоже должен быть аккуратным: его ошибка в finally способна перекрыть исходное исключение, а блокирующий ввод-вывод задержит весь event loop.
#python #asyncio
Почему max_workers не ограничивает очередь задач
ThreadPoolExecutor(max_workers=8) разрешает одновременно выполнять восемь вызовов. Если сразу вызвать submit для миллиона записей, остальные будут ждать, удерживая Future, аргументы и связанные объекты в памяти.
Окно незавершённой работы ограничивает и подачу: отправить, например, 32 задачи, дождаться завершений через wait(..., FIRST_COMPLETED), забрать результаты и только затем добавить новые. Производитель перестаёт бесконечно убегать вперёд.
В Python 3.14 для обработки с сохранением входного порядка есть executor.map(..., buffersize=32). Ручная схема удобнее, когда результаты нужны по готовности. Ни одна из этих границ не задаёт число запросов в секунду: для внешнего API ограничение частоты рассчитывают отдельно.
#python #производительность
ThreadPoolExecutor(max_workers=8) разрешает одновременно выполнять восемь вызовов. Если сразу вызвать submit для миллиона записей, остальные будут ждать, удерживая Future, аргументы и связанные объекты в памяти.
Окно незавершённой работы ограничивает и подачу: отправить, например, 32 задачи, дождаться завершений через wait(..., FIRST_COMPLETED), забрать результаты и только затем добавить новые. Производитель перестаёт бесконечно убегать вперёд.
В Python 3.14 для обработки с сохранением входного порядка есть executor.map(..., buffersize=32). Ручная схема удобнее, когда результаты нужны по готовности. Ни одна из этих границ не задаёт число запросов в секунду: для внешнего API ограничение частоты рассчитывают отдельно.
#python #производительность
Forwarded from Нейроканал
Showboat и Rodney помогают показать работу ИИ-агента
Саймон Уиллисон собирает демонстрации кода с помощью двух своих инструментов. Showboat выполняет команды и записывает их вывод в документ. Rodney управляет Chrome из командной строки и делает скриншоты интерфейса.
Эту команду автор предлагает дать агенту: в справке есть всё необходимое, чтобы тот создал документ с демонстрацией новой функции.
Уиллисон замечал и обход механизма: агент напрямую правит текст отчёта. Тогда записанный вывод может расходиться с реальным запуском. Содержимое демонстрации тоже требует проверки.
#ии #инструменты
Саймон Уиллисон собирает демонстрации кода с помощью двух своих инструментов. Showboat выполняет команды и записывает их вывод в документ. Rodney управляет Chrome из командной строки и делает скриншоты интерфейса.
uvx showboat --helpЭту команду автор предлагает дать агенту: в справке есть всё необходимое, чтобы тот создал документ с демонстрацией новой функции.
Уиллисон замечал и обход механизма: агент напрямую правит текст отчёта. Тогда записанный вывод может расходиться с реальным запуском. Содержимое демонстрации тоже требует проверки.
#ии #инструменты
Forwarded from Нейроканал
Вспомните последний раз, когда ИИ сделал для вас рабочий результат: код, тесты, документацию или требования. Как вы его проверяли?
Anonymous Poll
15%
Внимательно разобрал сам
37%
Проверил на практике: тесты, запуск, реальные данные
25%
И разобрал, и проверил на практике
2%
Отдал на ревью коллеге
13%
Не проверял, сразу использовал
5%
Не было такого случая или не помню
3%
Другое (напишу в комментариях)
Как проверить, что мок заменил нужную зависимость
Если service.py делает from client import fetch, функция использует имя service.fetch. Патч client.fetch не заменит уже импортированную ссылку: тест может продолжить обращаться к настоящему клиенту.
Правило patch — заменять имя там, где тестируемый код его ищет. Для этого примера нужен patch("service.fetch", autospec=True). autospec проверяет совместимость вызова с сигнатурой зависимости и помогает поймать лишний аргумент.
Для async-зависимости важно проверить await: assert_called_once_with доказывает только вызов, а assert_awaited_once_with — ожидание корутины. Дополнительно проверяйте возвращённое значение или эффект работы сервиса. Один счётчик вызовов не показывает, что результат зависимости был использован правильно.
#python #тестирование
Если service.py делает from client import fetch, функция использует имя service.fetch. Патч client.fetch не заменит уже импортированную ссылку: тест может продолжить обращаться к настоящему клиенту.
Правило patch — заменять имя там, где тестируемый код его ищет. Для этого примера нужен patch("service.fetch", autospec=True). autospec проверяет совместимость вызова с сигнатурой зависимости и помогает поймать лишний аргумент.
Для async-зависимости важно проверить await: assert_called_once_with доказывает только вызов, а assert_awaited_once_with — ожидание корутины. Дополнительно проверяйте возвращённое значение или эффект работы сервиса. Один счётчик вызовов не показывает, что результат зависимости был использован правильно.
#python #тестирование
Почему короткие паузы сборщика мусора обходятся памятью
В CPython подсчёт ссылок освобождает многие объекты сразу, а циклический GC ищет недостижимые циклы. Сокращение пауз этого дополнительного механизма важно для серверов и интерфейсов, но может изменить расход памяти.
В отчёте Language Summit Марк Шеннон разбирает откат инкрементального сборщика Python 3.14 после проблем с памятью на реальных нагрузках. Разделение обхода на небольшие части уменьшало длинные остановки, но дольше сохраняло часть объектов.
Обсуждаемое направление — совместить поколения с инкрементальным обходом молодых и старых объектов. Это предложение, а не настройка, которую уже можно включить. Для оценки изменений нужны одновременно длительность пауз, память и реальные сценарии приложения: улучшение одного показателя может ухудшить другой.
#python #cpython
В CPython подсчёт ссылок освобождает многие объекты сразу, а циклический GC ищет недостижимые циклы. Сокращение пауз этого дополнительного механизма важно для серверов и интерфейсов, но может изменить расход памяти.
В отчёте Language Summit Марк Шеннон разбирает откат инкрементального сборщика Python 3.14 после проблем с памятью на реальных нагрузках. Разделение обхода на небольшие части уменьшало длинные остановки, но дольше сохраняло часть объектов.
Обсуждаемое направление — совместить поколения с инкрементальным обходом молодых и старых объектов. Это предложение, а не настройка, которую уже можно включить. Для оценки изменений нужны одновременно длительность пауз, память и реальные сценарии приложения: улучшение одного показателя может ухудшить другой.
#python #cpython