Коробка с питоном

Коробка с питоном

@boxwithpython

Заметки от Python-разработчика: сниппеты, обзоры пакетов, новости и другая полезная информация.

507подписчиков
🇷🇺

Похожие каналы

Все →

Последние посты

Rapidy - новый web-фреимворк на базе aiohttpНедавно заметил, что в чатиках разгоняют про ещё один новый web-фреимворк, только уже построенный на aiohttp. Зачем, конечно, в 2025 году использовать aiohttp - вопрос сложный, но автор отвечает на него так - это для любителей aiohttp. Ну раз так, то ладно.Вообще, когда я писал сервисы на aiohttp, мне всегда хотелось иметь работу с pydantic как у FastAPI. Можно сказать, автор воплотил одну из моих идей.Что под капотом из того, что мне приглянулось?- Валидация и сериализация как в хендлерах, так и в middleware при помощи полюбившегося всем Pydantic.- Нативная интеграция с dishka.- Декларативные контроллеры в виде классов с наследованием параметров - вкусовщина ещё та, но мне нравится:@controller('/')class UserController: @get('/{user_id}') async def get_by_id(self, user_id: str = PathParam()) -> dict[str, str]: return {'user_id': user_id} @get() async def get_all_users(self) -> list[dict[str, str]]: return [{'name': 'John'}, {'name': 'Felix'}]- Ну и по стандарту, всё что уже и так есть в aiohttp.А обещают нам:- Генерацию OpenAPI - очень хотелось бы видеть.- HTTP клиент обмазанный Pydantic - видимо чтобы быстренько клепать интеграции с http-сервисами.- И, самое интересное - поддержку GRPC. Вот тут очень стало интересно, как это будет выглядеть.Всё это, конечно, звучит круто, но у фреимворка есть самый большой недостаток, который вытекает из самого aiohttp - нету asgi. Мне кажется, что если его исправить, то ему можно будет даже подвинуться между легким FastAPI и уже ставшим монструозным Litestar.Поэтому, пока что для меня - это aiohttp на стероидах. Удобный, легкий, слегка фичастый, подведенный к стандарту разработки 2025 года.Github | Документация#библиотека

24 мая 2025 г.923В Telegram
Коробка с питоном — пост в ТГ канале

Breaking: PEP 750 - Template Strings был принят: https://github.com/python/steering-council/issues/275#issuecomment-2794619570Вроде крутой PEP, но напрашиваются вопросы:1. Умрут ли всякие шаблонизаторы, по типу Jinja/Mako? В самом PEP пишут что они необходимы в качестве использования средства кастомизации, но выглядит все это так, как будто надстройки над Template смогут их заменить.2. В motivation написано, что якобы те, кто не осилили доку юзали f-строки для SQLек, что может привести к SQL-инъекциям, и мы щас темплейтами всё решим. А может не надо ничего решать? Это ведь проблемы этих разработчиков.3. Пикрилейтед. Ничего проклятее я сегодня не увижу. Вот это реально не стоило добавлять.Я конечно побухчу посижу, но всё равно буду пользоваться.#pep

10 апр. 2025 г.878В Telegram

Breaking: PEP 750 - Template Strings был принят:https://github.com/python/steering-council/issues/275#issuecomment-2794619570

10 апр. 2025 г.644В Telegram

В asyncio добавили возможность смотреть граф вызова корутинЖдем в python3.14: https://github.com/python/cpython/commit/188598851d5cf475fa57b4ec21c0e88ce9316ff0Пример:import asyncioasync def test(): asyncio.print_call_graph()async def main(): async with asyncio.TaskGroup() as g: g.create_task(test(), name=test.__name__)asyncio.run(main())Выведет:* Task(name='test', id=0x10304eee0) + Call stack: | File '/Users/sobolev/Desktop/cpython2/Lib/asyncio/graph.py', line 278, in print_call_graph() | File '/Users/sobolev/Desktop/cpython2/ex.py', line 4, in async test() + Awaited by: * Task(name='Task-1', id=0x1034a1e60) + Call stack: | File '/Users/sobolev/Desktop/cpython2/Lib/asyncio/taskgroups.py', line 121, in async TaskGroup._aexit() | File '/Users/sobolev/Desktop/cpython2/Lib/asyncio/taskgroups.py', line 72, in async TaskGroup.__aexit__() | File '/Users/sobolev/Desktop/cpython2/ex.py', line 7, in async main()Как оно работает?Появилось два новых важных изменений:- Поле Frame.f_generator – оно хранит генератор или корутину, которая владеет данным фреймом. Нужно чтобы отрисовывать + Call stack:- Новое свойство у Future @property def _asyncio_awaited_by(self): if self.__asyncio_awaited_by is None: return None return frozenset(self.__asyncio_awaited_by)Нужно, чтобы отрисовывать + Awaited by:.Конечно же есть две иплементации. На питоне уже показал, вот так оно на C:/*[clinic input]@critical_section@getter_asyncio.Future._asyncio_awaited_by[clinic start generated code]*/static PyObject *_asyncio_Future__asyncio_awaited_by_get_impl(FutureObj *self)/*[clinic end generated code: output=... input=...]*/{ /* Implementation of a Python getter. */ if (self->fut_awaited_by == NULL) { Py_RETURN_NONE; } if (self->fut_awaited_by_is_set) { /* Already a set, just wrap it into a frozen set and return. */ assert(PySet_CheckExact(self->fut_awaited_by)); return PyFrozenSet_New

23 янв. 2025 г.887В Telegram

Сегодня расскажу про модуль, который поможет остановить время в ваших тестах и не только - FreezeGunСначала история из жизни. Недавно мне принесли скрипт, который скрапил некоторую информацию с онлаин-каталога на текущий момент. Задачей было заставить его скрапить данные до определенного момента. В нём было очень много вызовов datetime.now() (пагинация по датам, ага), перепиливать все это мне не очень хотелось, а результат хотели вчера. Поэтому я такой хоп:from freezegun import freeze_timewith freeze_time("01-08-24"): result = call_api()И всё работает!Но вы так не делайте, конечно, это самый настоящий подпор костылём, мне вообще повезло, что оно заработало.Или делайте если надо, разрешаю.В основном этот пакет используют для тестов и как было понятно с примера выше - он позволяет "заморозить" время на определенном моменте.Проверить истечение подписки, корректность фильтров, расчёт на определенное время - этот пакет позволит сделать всё это всего в пару строк кода!Есть возможность использовать декоратор вместо контекстного менеджера:@freeze_time("2012-01-14")def test(): assert datetime.datetime.now() == datetime.datetime(2012, 1, 14)А если оба варианта вам не нравятся, и хочется более гибкого управления - можно руками задавать когда время остановится и возобновится:freezer = freeze_time("2012-01-14 12:00:01")freezer.start()assert datetime.datetime.now() == datetime.datetime(2012, 1, 14, 12, 0, 1)freezer.stop()С асинком, кстати, тоже работает. Библиотека довольно фичастая, так что за примерами использования можно проследовать в тесты.#библиотека

1 сент. 2024 г.1 160В Telegram
Коробка с питоном — пост в ТГ канале

Итак, ко мне пришли ребята из Podlodka Python Crew и предложили разыграть один бесплатный билет на новый сезон их конференции, где участников с 3 по 7 июня будет ждать целая неделя онлаин-воркшопов и много докладов по теме инфраструктуры. Из интересного:…Самым залайканным оказался вот этот мемас, приз отправлен автору!

2 июн. 2024 г.1 290В Telegram
Коробка с питоном — пост в ТГ канале

Итак, ко мне пришли ребята из Podlodka Python Crew и предложили разыграть один бесплатный билет на новый сезон их конференции, где участников с 3 по 7 июня будет ждать целая неделя онлаин-воркшопов и много докладов по теме инфраструктуры.Из интересного:— К ним придёт разработчик FastStream, про который я неоднократно рассказывал здесь, покажет насколько удобно можно работать с Kafka, RabbitMQ, NATS и другими брокерами.— Для енжоеров микросервисной архитектуры расскажут и покажут, как гарантировать консистентную работу всей системы при помощи паттерна "transactional outbox". Будет демо-стенд и реализация на практике.— Приложение без метрик - плохое приложение. Покажут как собирать и анализировать данные, чтобы всегда быть в курсе состояния системы.— Так же будут истории от экспертов про фейлы с инфраструктурой и как их можно избежать.А так же нетворкинг, много практических примеров и дискуссии!Чтобы попытать счастье, постите под этим постом любой мем про наш любимый язык до 02.06.24. Самый залайканный станет победителем - ему и отправится билет. А если пытать счастье не хочется - вот вам скидка в 500 рублей по промокоду `podlodka_boxwithpython`Ждем всех, тыкай чтобы попасть 😎

31 мая 2024 г.1 320В Telegram
Коробка с питоном — пост в ТГ канале

Да, оно существует.Под капотом низкоуровневая магия, из самого понятного - оно позволяет создавать поддельные объекты на куче. Можно создать байтовый массив с базовым адресом 0 и длинной SSIZE_MAX, что даст доступ к сырой памяти, на чтение и запись.Такая техника, кстати, используется в эксплоитах движков javascript. Парочкой похожих эксплоитов уже давно хакают PS4.

13 мая 2024 г.2 090В Telegram

Там в Python 3.12 добавили нашумевший PEP 659, а у меня пет-проект один давно не обновлялся, и так уж звёзды сошлись, что я сижу второй день обновляю его на 3.12Задача - есть функционал, который под капотом имеет некоторый класс следующего вида:class BaseFunction: serialize_to: None def serialize(self, data: dict) -> serialize_to: pass # тут мы используем наш serialize_to@dataclassclass ModelA: x: strclass FunctionA(BaseFunction): serialize_to: ModelAМы определяем новые классы наследуясь от BaseFunction, переопределяем в них serialize_to и вызываем serialize который делает нам инстанс serialize_to. Ну прямо дженерик напрашивается! Тем более в 3.12 их завезли, красивые:class BaseFunction[T]: def serialize(self, data: dict) -> T: pass # тут мы используем наш serialize_toclass FunctionA(BaseFunction[ModelA]): passВстаёт вопрос, а как нам получить наш тип из дженерика?Для начала, получим __orig_bases__[0] - он вернёт нам классы, от которых мы наследовались. Так как нам нужен только наш первый класс, мы указываем [0]:>>> FunctionA.__orig_bases____main__.BaseFunction[__main__.ModelA]Ещё можно это сделать с помощью get_original_bases из types, но его добавили только в 3.12 (почему я об этом сказал - узнаете ниже).Теперь надо получить получить сам тип в дженерике. В этом нам поможет typing.get_args, который получает все аргументы типа. Дополнительно укажем, что нам нужен первый тип:>>> get_args(FunctionA.__orig_bases__[0])[0]<class '__main__.ModelA'>Теперь в методе serialize класса BaseFunction[T] можно написать штуку, которая автоматически сериализует наши данные:def serialize(self, data: dict) -> T: type_from_generic = get_args(self.__class__.__orig_bases__[0])[0] return type_from_generic(**data)Проверяем:>>> f = FunctionA()>>> f.serialize(data={"x": 1})ModelA(x=1)Вы восхитительны!Кстати, эта же штука должна работать ещё вроде как аж с 3.8, так как в нём именно был добавлен __orig_bases__ (PEP 560), ну и под капотом у новых дженерико

11 мая 2024 г.1 120В Telegram
Коробка с питоном — пост в ТГ канале

Dishka - IoC-контейнер для PythonКогда мы следуем подходу Dependency Injection, а особенно - слоистой архитектуре, у нас образуется отдельная группа функций и классов, выполняющих только одну задачу - создание других объектов. Такой код лучше держать поближе к main, так как он связывает воедино разные части приложения и связан с конфигурацией запуска.В сложном приложении такой компонент может содержать большое количество функций, контролировать как создание, так и корректную очистку объектов и, что самое главное, их взаимосвязь. Для упрощения работы с такими фабриками придумали отдельный тип библиотек - IoC-контейнеры (DI-фреймворки).В Python меня долго не устраивали существующие контейнеры и я решил сделать свой:Хочу представить вам Dishka 1.0Цель этого проекта - предоставить простой и удобный IoC-контейнер, который сможет забрать всю работу с зависимостями. Мне кажется, на текущий момент это самый функциональный вариант контейнера, имеющий при этом самое простое API.• Вы можете использовать его с любым фреймворком, но для некоторых мы уже подготовили хелперы• Для создания зависимости можно указать отдельную функцию или использовать __init__ класса• Зависимости имеют ограниченное время жизни (скоуп) и вы сами управляете им• Зависимости кэшируются, поэтому один и тот же объект может быть переиспользован пока он жив. Так можно передать одно соединение с БД в несколько гейтвеев• Фабрики зависимостей можно группировать в классы и компоненты, что позволяет делать контейнер модульным• Можно декорировать объекты, использовать один объект для нескольких типов• При старте проверяется корректность конфигурации контейнера, что позволяет исключить многие ошибкиЧто значит версия 1.0?У библиотеки было 9 промежуточных релизов, мы ради объявить, что закончена вся работа по стабилизации её интерфейса и исправлению ошибок. И у нас есть планы по развитию, уникальные фичи сами себя не напишут.Будем рады новым пользователям, багрепортам, запросам фич и звездам на гитхабе• Github• Pypi•

3 апр. 2024 г.934В Telegram

Подписчиков набежало, а постов всё так же не было. Буду исправляться!Сегодня расскажу про deptry - тулзу, которая позволяет находить неиспользованные, транзитивные или отсутствующие зависимости в проекте на Python. Работает это следующим образом - запускаем утилиту в каталоге с проектом, она сканит все импортированные модули и сравнивает их с тем, что описано в зависимостях. Умеет работать с любым пакетным менеджером который строго следует PEP 621, а так же pyproject.toml от Poetry и PDM. Ну и обычный requirements.txt тоже поддерживается!Где это может быть полезно? Для себя выявил несколько сценариев:1. Получили старый проект без зависимостей и пытаемся собрать либы, которые он использует (много раз такое было на фрилансе). 2. Проводим глубокий рефакторинг, трекаем ненужные зависимости и таким образом избавляемся от них.3. Если кто-то напихал нормальные зависимости в качестве dev зависимостей, утилита тоже это покажет.4. Отлично детектит использование транзитивных зависимостей - это такие пакеты, которые мы не устанавливаем напрямую, но которые устанавливаются при установке другого пакета как его зависимость. Самый простой пример - установка sqlparse при установке Django. Такие зависимости должны быть указаны явно.5. Добавляем в CI и время от времени смотрим отчеты, таким образом поддерживаем зависимости в нормальном виде.Настраивается достаточно гибко, документация лежит здесь.#утилита

21 мар. 2024 г.1 040В Telegram

Совсем скоро (релиз запланирован на конец января - начало февраля) выйдет NumPy 2. Список изменений можно прочитать здесь, а информацию по миграции - здесь. Статус и анонсы можно читать здесь.Изменений в API очень много, поэтому рекомендую зайти в свои проекты и зафиксировать зависимости. По большей части релиз выглядит как рефакторинг API.Некоторые функции, модули, константы переместили или удалили, чтобы сделать неимспейсы более удобными и чистыми. Про это можно прочитать в NEP 52. Релиз так же затронет юзеров с Виндой - теперь int в numpy 64х-разрядный (для 32х систем - 32х-разрядный), хотя ранее, по историческим причинам, связанных Python 2, был эквивалентен типу long в C.

18 янв. 2024 г.1 300В Telegram
Коробка с питоном — пост в ТГ канале

Тренажер по тайпингу в Python для самых маленьких (и не только)Python Type Challenges, очень прикольный сайт-тренажер для изучения типизации. Выбираешь тему, дописываешь необходимые куски кода и запускаешь проверку линтером. Почти как олимпиадные задачки, только полезные😁Для некоторых задач доступны подсказки со ссылками на документацию.Проверить свои знания по типам сюда Посмотреть исходный код сюда

15 янв. 2024 г.1 120В Telegram

С наступившим 2024 вас! Сегодня расскажу про dirty-equals.Этот пакет используется для реализации более читаемых и декларативных проверок на равенство/соответствие, но в полной мере он себя раскрывает при написании тестов. Как обычно, приведу несколько примеров:from dirty_equals import *>>> assert 1 == IsPositive # Всё ок, число положительное>>> assert -2 == IsPositive # AssertionError>>> # Проверки можно комбинировать при помощи булевой логики>>> assert ['a', 'b', 'c'] == HasLen(3) & Contains('a') # Ок, список на 3 элемента, содержит 'a'>>> # Есть проверка словарей>>> assert {'a': 1, 'b': 2} == IsDict(a=1, b=2)>>> # Словари можно проверять частично>>> assert {'a': 1, 'b': 2, 'c': 3} == IsDict(a=1, b=2).settings(partial=True)>>> # Или вот так>>> assert {'a': 1, 'b': 2, 'c': 3} == IsPartialDict(a=1, b=2)>>> Можно проверять соответствие регуляркам>>> assert 'test@kiriha.ru' == IsStr(regex=r'^[^@]+@[^@]+\.[^@]+$')>>> # И так далее...Рекомендую заглянуть в документацию, там таких удобных штук ещё очень много! Ну и изучите исходники - написано не сложно, под капотом используется чуток метаклассов, для изучения темы - самое то!#библиотека

1 янв. 2024 г.1 200В Telegram